aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/org/traccar/protocol
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/org/traccar/protocol')
-rw-r--r--src/main/java/org/traccar/protocol/AdmProtocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/AisProtocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/AlematicsProtocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/AnytrekProtocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/ApelProtocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/AplicomProtocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/AppelloProtocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/AquilaProtocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/Ardi01Protocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/ArknavProtocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/ArknavX8Protocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/ArmoliProtocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/ArnaviProtocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/ArnaviProtocolDecoder.java2
-rw-r--r--src/main/java/org/traccar/protocol/AstraProtocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/At2000Protocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/AtrackProtocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/AtrackProtocolDecoder.java202
-rw-r--r--src/main/java/org/traccar/protocol/AuroProtocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/AustinNbProtocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/AutoFonProtocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/AutoGradeProtocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/AutoTrackProtocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/AvemaProtocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/Avl301Protocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/B2316Protocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/B2316ProtocolDecoder.java6
-rw-r--r--src/main/java/org/traccar/protocol/BceProtocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/BlackKiteProtocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/BlueProtocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/BoxProtocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/BstplProtocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/C2stekProtocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/CalAmpProtocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/CarTrackProtocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/CarcellProtocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/CarscopProtocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/CastelProtocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/CastelProtocolDecoder.java33
-rw-r--r--src/main/java/org/traccar/protocol/CautelaProtocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/CellocatorProtocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/CguardProtocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/CityeasyProtocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/ContinentalProtocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/CradlepointProtocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/DingtekProtocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/DishaProtocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/DmtHttpProtocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/DmtHttpProtocolDecoder.java6
-rw-r--r--src/main/java/org/traccar/protocol/DmtProtocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/DolphinProtocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/DraginoProtocol.java42
-rw-r--r--src/main/java/org/traccar/protocol/DraginoProtocolDecoder.java78
-rw-r--r--src/main/java/org/traccar/protocol/Dsf22Protocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/DualcamProtocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/DualcamProtocolDecoder.java59
-rw-r--r--src/main/java/org/traccar/protocol/DwayProtocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/EasyTrackProtocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/EasyTrackProtocolDecoder.java70
-rw-r--r--src/main/java/org/traccar/protocol/EelinkProtocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/EelinkProtocolDecoder.java2
-rw-r--r--src/main/java/org/traccar/protocol/EgtsProtocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/EnforaProtocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/EnnfuProtocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/EnvotechProtocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/EsealProtocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/EskyProtocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/ExtremTracProtocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/FifotrackProtocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/FifotrackProtocolDecoder.java21
-rw-r--r--src/main/java/org/traccar/protocol/FleetGuideProtocol.java36
-rw-r--r--src/main/java/org/traccar/protocol/FleetGuideProtocolDecoder.java328
-rw-r--r--src/main/java/org/traccar/protocol/FlespiProtocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/FlespiProtocolDecoder.java26
-rw-r--r--src/main/java/org/traccar/protocol/FlexApiProtocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/FlexApiProtocolDecoder.java4
-rw-r--r--src/main/java/org/traccar/protocol/FlexCommProtocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/FlexibleReportProtocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/FlextrackProtocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/FoxProtocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/FreedomProtocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/FreematicsProtocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/FreematicsProtocolDecoder.java4
-rw-r--r--src/main/java/org/traccar/protocol/FutureWayProtocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/G1rusProtocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/GalileoFrameDecoder.java16
-rw-r--r--src/main/java/org/traccar/protocol/GalileoProtocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/GatorProtocol.java10
-rw-r--r--src/main/java/org/traccar/protocol/GatorProtocolDecoder.java5
-rw-r--r--src/main/java/org/traccar/protocol/GatorProtocolEncoder.java93
-rw-r--r--src/main/java/org/traccar/protocol/GenxProtocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/Gl100Protocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/Gl200Protocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/Gl200ProtocolDecoder.java2
-rw-r--r--src/main/java/org/traccar/protocol/Gl200TextProtocolDecoder.java1388
-rw-r--r--src/main/java/org/traccar/protocol/GlobalSatProtocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/GlobalstarProtocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/GlobalstarProtocolDecoder.java56
-rw-r--r--src/main/java/org/traccar/protocol/GnxProtocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/GoSafeProtocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/GoSafeProtocolDecoder.java12
-rw-r--r--src/main/java/org/traccar/protocol/GotopProtocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/Gps056Protocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/Gps103Protocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/Gps103ProtocolDecoder.java2
-rw-r--r--src/main/java/org/traccar/protocol/GpsGateProtocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/GpsMarkerProtocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/GpsmtaProtocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/GranitProtocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/Gs100Protocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/Gt02Protocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/Gt06Protocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/Gt06ProtocolDecoder.java227
-rw-r--r--src/main/java/org/traccar/protocol/Gt06ProtocolEncoder.java7
-rw-r--r--src/main/java/org/traccar/protocol/Gt30Protocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/H02Protocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/HaicomProtocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/HomtecsProtocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/HoopoProtocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/HoopoProtocolDecoder.java4
-rw-r--r--src/main/java/org/traccar/protocol/HuaShengProtocol.java12
-rw-r--r--src/main/java/org/traccar/protocol/HuaShengProtocolDecoder.java22
-rw-r--r--src/main/java/org/traccar/protocol/HuaShengProtocolEncoder.java85
-rw-r--r--src/main/java/org/traccar/protocol/HuabaoProtocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/HuabaoProtocolDecoder.java283
-rw-r--r--src/main/java/org/traccar/protocol/HunterProProtocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/IdplProtocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/IntellitracProtocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/IotmProtocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/IotmProtocolDecoder.java147
-rw-r--r--src/main/java/org/traccar/protocol/ItsProtocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/Ivt401Protocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/JidoProtocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/JpKorjarProtocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/Jt600FrameDecoder.java2
-rw-r--r--src/main/java/org/traccar/protocol/Jt600Protocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/Jt600ProtocolDecoder.java24
-rw-r--r--src/main/java/org/traccar/protocol/KenjiProtocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/KhdProtocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/KhdProtocolDecoder.java25
-rw-r--r--src/main/java/org/traccar/protocol/L100Protocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/LacakProtocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/LacakProtocolDecoder.java4
-rw-r--r--src/main/java/org/traccar/protocol/LaipacProtocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/LaipacProtocolDecoder.java33
-rw-r--r--src/main/java/org/traccar/protocol/LeafSpyProtocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/M2cProtocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/M2mProtocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/MaestroProtocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/ManPowerProtocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/Mavlink2Protocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/MegastekProtocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/MeiligaoProtocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/MeiligaoProtocolDecoder.java2
-rw-r--r--src/main/java/org/traccar/protocol/MeiligaoProtocolEncoder.java3
-rw-r--r--src/main/java/org/traccar/protocol/MeitrackProtocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/MeitrackProtocolDecoder.java96
-rw-r--r--src/main/java/org/traccar/protocol/MictrackProtocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/MilesmateProtocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/MiniFinderProtocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/MiniFinderProtocolDecoder.java16
-rw-r--r--src/main/java/org/traccar/protocol/Minifinder2Protocol.java11
-rw-r--r--src/main/java/org/traccar/protocol/Minifinder2ProtocolDecoder.java231
-rw-r--r--src/main/java/org/traccar/protocol/Minifinder2ProtocolEncoder.java72
-rw-r--r--src/main/java/org/traccar/protocol/MobilogixProtocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/MoovboxProtocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/MotorProtocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/Mta6Protocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/Mta6ProtocolDecoder.java2
-rw-r--r--src/main/java/org/traccar/protocol/MtxProtocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/MxtProtocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/NavigilProtocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/NavisProtocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/NavisetProtocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/NavtelecomProtocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/NavtelecomProtocolDecoder.java135
-rw-r--r--src/main/java/org/traccar/protocol/NdtpV6Protocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/NeosProtocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/NetProtocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/NiotProtocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/NoranProtocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/NtoProtocol.java42
-rw-r--r--src/main/java/org/traccar/protocol/NtoProtocolDecoder.java92
-rw-r--r--src/main/java/org/traccar/protocol/NvsProtocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/NyitechProtocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/ObdDongleProtocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/OigoProtocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/OkoProtocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/OmnicommProtocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/OpenGtsProtocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/OrbcommProtocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/OrbcommProtocolDecoder.java8
-rw-r--r--src/main/java/org/traccar/protocol/OrionProtocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/OsmAndProtocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/OutsafeProtocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/OutsafeProtocolDecoder.java10
-rw-r--r--src/main/java/org/traccar/protocol/OwnTracksProtocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/OwnTracksProtocolDecoder.java4
-rw-r--r--src/main/java/org/traccar/protocol/PacificTrackProtocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/PathAwayProtocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/PiligrimProtocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/PluginProtocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/PolteProtocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/PolteProtocolDecoder.java4
-rw-r--r--src/main/java/org/traccar/protocol/PortmanProtocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/PortmanProtocolDecoder.java24
-rw-r--r--src/main/java/org/traccar/protocol/PositrexProtocol.java36
-rw-r--r--src/main/java/org/traccar/protocol/PositrexProtocolDecoder.java116
-rw-r--r--src/main/java/org/traccar/protocol/PretraceProtocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/PricolProtocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/ProgressProtocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/PstProtocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/Pt215Protocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/Pt3000Protocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/Pt502Protocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/Pt60Protocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/PuiProtocol.java40
-rw-r--r--src/main/java/org/traccar/protocol/PuiProtocolDecoder.java73
-rw-r--r--src/main/java/org/traccar/protocol/R12wProtocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/RaceDynamicsProtocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/RadarProtocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/RamacProtocol.java42
-rw-r--r--src/main/java/org/traccar/protocol/RamacProtocolDecoder.java112
-rw-r--r--src/main/java/org/traccar/protocol/RaveonProtocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/RecodaProtocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/RetranslatorProtocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/RfTrackProtocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/RfTrackProtocolDecoder.java6
-rw-r--r--src/main/java/org/traccar/protocol/RitiProtocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/RoboTrackProtocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/RstProtocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/RstProtocolDecoder.java36
-rw-r--r--src/main/java/org/traccar/protocol/RuptelaProtocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/RuptelaProtocolDecoder.java167
-rw-r--r--src/main/java/org/traccar/protocol/S168Protocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/SabertekProtocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/SanavProtocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/SanulProtocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/SatsolProtocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/SigfoxProtocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/SigfoxProtocolDecoder.java36
-rw-r--r--src/main/java/org/traccar/protocol/SiwiProtocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/SkypatrolProtocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/SmartSoleProtocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/SmokeyProtocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/SolarPoweredProtocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/SpotProtocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/StarLinkProtocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/StarLinkProtocolDecoder.java4
-rw-r--r--src/main/java/org/traccar/protocol/StarcomProtocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/StarcomProtocolDecoder.java4
-rw-r--r--src/main/java/org/traccar/protocol/StartekFrameDecoder.java (renamed from src/main/java/org/traccar/protocol/NdtpV6FrameDecoder.java)23
-rw-r--r--src/main/java/org/traccar/protocol/StartekProtocol.java7
-rw-r--r--src/main/java/org/traccar/protocol/StartekProtocolDecoder.java139
-rw-r--r--src/main/java/org/traccar/protocol/StbProtocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/StbProtocolDecoder.java6
-rw-r--r--src/main/java/org/traccar/protocol/Stl060Protocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/SuntechProtocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/SuntechProtocolDecoder.java29
-rw-r--r--src/main/java/org/traccar/protocol/SupermateProtocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/SviasProtocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/SwiftechProtocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/T55Protocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/T55ProtocolDecoder.java51
-rw-r--r--src/main/java/org/traccar/protocol/T57Protocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/T622IridiumProtocol.java39
-rw-r--r--src/main/java/org/traccar/protocol/T622IridiumProtocolDecoder.java149
-rw-r--r--src/main/java/org/traccar/protocol/T800xProtocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/T800xProtocolDecoder.java16
-rw-r--r--src/main/java/org/traccar/protocol/TaipPrefixEncoder.java24
-rw-r--r--src/main/java/org/traccar/protocol/TaipProtocol.java13
-rw-r--r--src/main/java/org/traccar/protocol/TaipProtocolDecoder.java28
-rw-r--r--src/main/java/org/traccar/protocol/TechTltProtocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/TechtoCruzProtocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/TekProtocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/TelemaxProtocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/TelicProtocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/TeltonikaFrameDecoder.java2
-rw-r--r--src/main/java/org/traccar/protocol/TeltonikaProtocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/TeltonikaProtocolDecoder.java120
-rw-r--r--src/main/java/org/traccar/protocol/TeraTrackProtocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/TeraTrackProtocolDecoder.java6
-rw-r--r--src/main/java/org/traccar/protocol/ThinkPowerProtocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/ThinkRaceProtocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/ThurayaProtocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/Tk102Protocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/Tk103Protocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/Tk103ProtocolDecoder.java107
-rw-r--r--src/main/java/org/traccar/protocol/Tlt2hProtocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/Tlt2hProtocolDecoder.java53
-rw-r--r--src/main/java/org/traccar/protocol/TlvProtocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/TmgProtocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/TopflytechProtocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/TopinProtocol.java11
-rw-r--r--src/main/java/org/traccar/protocol/TopinProtocolDecoder.java8
-rw-r--r--src/main/java/org/traccar/protocol/TotemProtocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/TotemProtocolDecoder.java175
-rw-r--r--src/main/java/org/traccar/protocol/Tr20Protocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/Tr900Protocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/TrackboxProtocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/TrakMateProtocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/TramigoFrameDecoder.java8
-rw-r--r--src/main/java/org/traccar/protocol/TramigoProtocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/TramigoProtocolDecoder.java264
-rw-r--r--src/main/java/org/traccar/protocol/TranSyncProtocol.java39
-rw-r--r--src/main/java/org/traccar/protocol/TranSyncProtocolDecoder.java166
-rw-r--r--src/main/java/org/traccar/protocol/TrvProtocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/TrvProtocolDecoder.java43
-rw-r--r--src/main/java/org/traccar/protocol/Tt8850Protocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/TytanProtocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/TzoneProtocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/TzoneProtocolDecoder.java37
-rw-r--r--src/main/java/org/traccar/protocol/UlbotechProtocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/UproProtocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/UproProtocolDecoder.java4
-rw-r--r--src/main/java/org/traccar/protocol/UuxProtocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/V680Protocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/ValtrackProtocol.java41
-rw-r--r--src/main/java/org/traccar/protocol/ValtrackProtocolDecoder.java84
-rw-r--r--src/main/java/org/traccar/protocol/VisiontekProtocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/VltProtocol.java43
-rw-r--r--src/main/java/org/traccar/protocol/VltProtocolDecoder.java139
-rw-r--r--src/main/java/org/traccar/protocol/VnetProtocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/Vt200Protocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/Vt200ProtocolDecoder.java2
-rw-r--r--src/main/java/org/traccar/protocol/VtfmsProtocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/WatchFrameDecoder.java23
-rw-r--r--src/main/java/org/traccar/protocol/WatchProtocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/WatchProtocolDecoder.java7
-rw-r--r--src/main/java/org/traccar/protocol/WialonProtocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/WialonProtocolDecoder.java21
-rw-r--r--src/main/java/org/traccar/protocol/WliProtocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/WondexProtocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/WristbandProtocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/Xexun2Protocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/Xexun2ProtocolDecoder.java4
-rw-r--r--src/main/java/org/traccar/protocol/XexunProtocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/XirgoProtocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/Xrb28Protocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/Xrb28ProtocolDecoder.java51
-rw-r--r--src/main/java/org/traccar/protocol/Xt013Protocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/Xt2400Protocol.java2
-rw-r--r--src/main/java/org/traccar/protocol/Xt2400ProtocolDecoder.java2
-rw-r--r--src/main/java/org/traccar/protocol/YwtProtocol.java2
344 files changed, 5727 insertions, 1539 deletions
diff --git a/src/main/java/org/traccar/protocol/AdmProtocol.java b/src/main/java/org/traccar/protocol/AdmProtocol.java
index bab1d2339..3856dc906 100644
--- a/src/main/java/org/traccar/protocol/AdmProtocol.java
+++ b/src/main/java/org/traccar/protocol/AdmProtocol.java
@@ -22,7 +22,7 @@ import org.traccar.TrackerServer;
import org.traccar.config.Config;
import org.traccar.model.Command;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class AdmProtocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/AisProtocol.java b/src/main/java/org/traccar/protocol/AisProtocol.java
index bc975c277..e792a1d3f 100644
--- a/src/main/java/org/traccar/protocol/AisProtocol.java
+++ b/src/main/java/org/traccar/protocol/AisProtocol.java
@@ -21,7 +21,7 @@ import org.traccar.PipelineBuilder;
import org.traccar.TrackerServer;
import org.traccar.config.Config;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class AisProtocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/AlematicsProtocol.java b/src/main/java/org/traccar/protocol/AlematicsProtocol.java
index b85b44382..5219607e7 100644
--- a/src/main/java/org/traccar/protocol/AlematicsProtocol.java
+++ b/src/main/java/org/traccar/protocol/AlematicsProtocol.java
@@ -22,7 +22,7 @@ import org.traccar.PipelineBuilder;
import org.traccar.TrackerServer;
import org.traccar.config.Config;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class AlematicsProtocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/AnytrekProtocol.java b/src/main/java/org/traccar/protocol/AnytrekProtocol.java
index b0e974c69..5dce15ce1 100644
--- a/src/main/java/org/traccar/protocol/AnytrekProtocol.java
+++ b/src/main/java/org/traccar/protocol/AnytrekProtocol.java
@@ -23,7 +23,7 @@ import org.traccar.config.Config;
import java.nio.ByteOrder;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class AnytrekProtocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/ApelProtocol.java b/src/main/java/org/traccar/protocol/ApelProtocol.java
index f1d6e659c..550581b85 100644
--- a/src/main/java/org/traccar/protocol/ApelProtocol.java
+++ b/src/main/java/org/traccar/protocol/ApelProtocol.java
@@ -22,7 +22,7 @@ import org.traccar.TrackerServer;
import org.traccar.config.Config;
import java.nio.ByteOrder;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class ApelProtocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/AplicomProtocol.java b/src/main/java/org/traccar/protocol/AplicomProtocol.java
index 47bb780cb..48c628d22 100644
--- a/src/main/java/org/traccar/protocol/AplicomProtocol.java
+++ b/src/main/java/org/traccar/protocol/AplicomProtocol.java
@@ -20,7 +20,7 @@ import org.traccar.PipelineBuilder;
import org.traccar.TrackerServer;
import org.traccar.config.Config;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class AplicomProtocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/AppelloProtocol.java b/src/main/java/org/traccar/protocol/AppelloProtocol.java
index 25b2bf3b8..34055d7e4 100644
--- a/src/main/java/org/traccar/protocol/AppelloProtocol.java
+++ b/src/main/java/org/traccar/protocol/AppelloProtocol.java
@@ -23,7 +23,7 @@ import org.traccar.PipelineBuilder;
import org.traccar.TrackerServer;
import org.traccar.config.Config;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class AppelloProtocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/AquilaProtocol.java b/src/main/java/org/traccar/protocol/AquilaProtocol.java
index 6080df33d..bd9c34d08 100644
--- a/src/main/java/org/traccar/protocol/AquilaProtocol.java
+++ b/src/main/java/org/traccar/protocol/AquilaProtocol.java
@@ -23,7 +23,7 @@ import org.traccar.PipelineBuilder;
import org.traccar.TrackerServer;
import org.traccar.config.Config;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class AquilaProtocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/Ardi01Protocol.java b/src/main/java/org/traccar/protocol/Ardi01Protocol.java
index b33c2817f..5ddbe9d62 100644
--- a/src/main/java/org/traccar/protocol/Ardi01Protocol.java
+++ b/src/main/java/org/traccar/protocol/Ardi01Protocol.java
@@ -23,7 +23,7 @@ import org.traccar.PipelineBuilder;
import org.traccar.TrackerServer;
import org.traccar.config.Config;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class Ardi01Protocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/ArknavProtocol.java b/src/main/java/org/traccar/protocol/ArknavProtocol.java
index 4f443aa3a..20fec296c 100644
--- a/src/main/java/org/traccar/protocol/ArknavProtocol.java
+++ b/src/main/java/org/traccar/protocol/ArknavProtocol.java
@@ -23,7 +23,7 @@ import org.traccar.PipelineBuilder;
import org.traccar.TrackerServer;
import org.traccar.config.Config;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class ArknavProtocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/ArknavX8Protocol.java b/src/main/java/org/traccar/protocol/ArknavX8Protocol.java
index 39c6e8009..a8be6f40c 100644
--- a/src/main/java/org/traccar/protocol/ArknavX8Protocol.java
+++ b/src/main/java/org/traccar/protocol/ArknavX8Protocol.java
@@ -23,7 +23,7 @@ import org.traccar.PipelineBuilder;
import org.traccar.TrackerServer;
import org.traccar.config.Config;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class ArknavX8Protocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/ArmoliProtocol.java b/src/main/java/org/traccar/protocol/ArmoliProtocol.java
index 32fba3b52..e9c947ecd 100644
--- a/src/main/java/org/traccar/protocol/ArmoliProtocol.java
+++ b/src/main/java/org/traccar/protocol/ArmoliProtocol.java
@@ -23,7 +23,7 @@ import org.traccar.PipelineBuilder;
import org.traccar.TrackerServer;
import org.traccar.config.Config;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class ArmoliProtocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/ArnaviProtocol.java b/src/main/java/org/traccar/protocol/ArnaviProtocol.java
index 091d5c06f..962bcce52 100644
--- a/src/main/java/org/traccar/protocol/ArnaviProtocol.java
+++ b/src/main/java/org/traccar/protocol/ArnaviProtocol.java
@@ -20,7 +20,7 @@ import org.traccar.PipelineBuilder;
import org.traccar.TrackerServer;
import org.traccar.config.Config;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class ArnaviProtocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/ArnaviProtocolDecoder.java b/src/main/java/org/traccar/protocol/ArnaviProtocolDecoder.java
index 361eeeef2..50ceea898 100644
--- a/src/main/java/org/traccar/protocol/ArnaviProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/ArnaviProtocolDecoder.java
@@ -21,7 +21,7 @@ import io.netty.channel.Channel;
import org.traccar.BaseProtocolDecoder;
import org.traccar.Protocol;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
import java.net.SocketAddress;
public class ArnaviProtocolDecoder extends BaseProtocolDecoder {
diff --git a/src/main/java/org/traccar/protocol/AstraProtocol.java b/src/main/java/org/traccar/protocol/AstraProtocol.java
index 021a81e07..dcc02d10d 100644
--- a/src/main/java/org/traccar/protocol/AstraProtocol.java
+++ b/src/main/java/org/traccar/protocol/AstraProtocol.java
@@ -21,7 +21,7 @@ import org.traccar.PipelineBuilder;
import org.traccar.TrackerServer;
import org.traccar.config.Config;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class AstraProtocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/At2000Protocol.java b/src/main/java/org/traccar/protocol/At2000Protocol.java
index 25e9be86f..c7e22f142 100644
--- a/src/main/java/org/traccar/protocol/At2000Protocol.java
+++ b/src/main/java/org/traccar/protocol/At2000Protocol.java
@@ -20,7 +20,7 @@ import org.traccar.PipelineBuilder;
import org.traccar.TrackerServer;
import org.traccar.config.Config;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class At2000Protocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/AtrackProtocol.java b/src/main/java/org/traccar/protocol/AtrackProtocol.java
index 21eb09696..8b86955f4 100644
--- a/src/main/java/org/traccar/protocol/AtrackProtocol.java
+++ b/src/main/java/org/traccar/protocol/AtrackProtocol.java
@@ -21,7 +21,7 @@ import org.traccar.TrackerServer;
import org.traccar.config.Config;
import org.traccar.model.Command;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class AtrackProtocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/AtrackProtocolDecoder.java b/src/main/java/org/traccar/protocol/AtrackProtocolDecoder.java
index 340641729..8896dcfb0 100644
--- a/src/main/java/org/traccar/protocol/AtrackProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/AtrackProtocolDecoder.java
@@ -429,6 +429,208 @@ public class AtrackProtocolDecoder extends BaseProtocolDecoder {
case "MP":
buf.readUnsignedByte(); // manifold absolute pressure
break;
+ case "EO":
+ position.set(Position.KEY_ODOMETER, UnitsConverter.metersFromMiles(buf.readUnsignedInt()));
+ break;
+ case "EH":
+ position.set(Position.KEY_HOURS, buf.readUnsignedInt() * 360000);
+ break;
+ case "ZO1":
+ buf.readUnsignedByte(); // brake stroke status
+ break;
+ case "ZO2":
+ buf.readUnsignedByte(); // warning indicator status
+ break;
+ case "ZO3":
+ buf.readUnsignedByte(); // abs control status
+ break;
+ case "ZO4":
+ position.set(Position.KEY_THROTTLE, buf.readUnsignedByte() * 0.4);
+ break;
+ case "ZO5":
+ buf.readUnsignedByte(); // parking brake status
+ break;
+ case "ZO6":
+ position.set(Position.KEY_OBD_SPEED, buf.readUnsignedByte() * 0.805);
+ break;
+ case "ZO7":
+ buf.readUnsignedByte(); // cruise control status
+ break;
+ case "ZO8":
+ buf.readUnsignedByte(); // accelector pedal position
+ break;
+ case "ZO9":
+ position.set(Position.KEY_ENGINE_LOAD, buf.readUnsignedByte() * 0.5);
+ break;
+ case "ZO10":
+ position.set(Position.KEY_FUEL_LEVEL, buf.readUnsignedByte() * 0.5);
+ break;
+ case "ZO11":
+ buf.readUnsignedByte(); // engine oil pressure
+ break;
+ case "ZO12":
+ buf.readUnsignedByte(); // boost pressure
+ break;
+ case "ZO13":
+ buf.readUnsignedByte(); // intake temperature
+ break;
+ case "ZO14":
+ position.set(Position.KEY_COOLANT_TEMP, buf.readUnsignedByte());
+ break;
+ case "ZO15":
+ buf.readUnsignedByte(); // brake application pressure
+ break;
+ case "ZO16":
+ buf.readUnsignedByte(); // brake primary pressure
+ break;
+ case "ZO17":
+ buf.readUnsignedByte(); // brake secondary pressure
+ break;
+ case "ZH1":
+ buf.readUnsignedShort(); // cargo weight
+ break;
+ case "ZH2":
+ position.set(Position.KEY_FUEL_CONSUMPTION, buf.readUnsignedShort() * 16.428 / 3600);
+ break;
+ case "ZH3":
+ position.set(Position.KEY_RPM, buf.readUnsignedShort() * 0.25);
+ break;
+ case "ZL1":
+ buf.readUnsignedInt(); // fuel used (natural gas)
+ break;
+ case "ZL2":
+ position.set(Position.KEY_ODOMETER, buf.readUnsignedInt() * 161);
+ break;
+ case "ZL3":
+ buf.readUnsignedInt(); // vehicle hours
+ break;
+ case "ZL4":
+ position.set(Position.KEY_HOURS, buf.readUnsignedInt() * 5 * 36000);
+ break;
+ case "ZS1":
+ position.set(Position.KEY_VIN, readString(buf));
+ break;
+ case "JO1":
+ buf.readUnsignedByte(); // pedals
+ break;
+ case "JO2":
+ buf.readUnsignedByte(); // power takeoff device
+ break;
+ case "JO3":
+ buf.readUnsignedByte(); // accelector pedal position
+ break;
+ case "JO4":
+ position.set(Position.KEY_ENGINE_LOAD, buf.readUnsignedByte());
+ break;
+ case "JO5":
+ position.set(Position.KEY_FUEL_LEVEL, buf.readUnsignedByte() * 0.4);
+ break;
+ case "JO6":
+ buf.readUnsignedByte(); // fms vehicle interface
+ break;
+ case "JO7":
+ buf.readUnsignedByte(); // driver 2
+ break;
+ case "JO8":
+ buf.readUnsignedByte(); // driver 1
+ break;
+ case "JO9":
+ buf.readUnsignedByte(); // drivers
+ break;
+ case "JO10":
+ buf.readUnsignedByte(); // system information
+ break;
+ case "JO11":
+ position.set(Position.KEY_COOLANT_TEMP, buf.readUnsignedByte() - 40);
+ break;
+ case "JO12":
+ buf.readUnsignedByte(); // pto engaged
+ break;
+ case "JH1":
+ position.set(Position.KEY_OBD_SPEED, buf.readUnsignedShort() / 256.0);
+ break;
+ case "JH2":
+ position.set(Position.KEY_RPM, buf.readUnsignedShort() * 0.125);
+ break;
+ case "JH3":
+ case "JH4":
+ case "JH5":
+ case "JH6":
+ case "JH7":
+ int index = Integer.parseInt(key.substring(2)) - 2;
+ position.set("axleWeight" + index, buf.readUnsignedShort() * 0.5);
+ break;
+ case "JH8":
+ position.set(Position.KEY_ODOMETER_SERVICE, buf.readUnsignedShort() * 5);
+ break;
+ case "JH9":
+ buf.readUnsignedShort(); // tachograph speed
+ break;
+ case "JH10":
+ buf.readUnsignedShort(); // ambient air temperature
+ break;
+ case "JH11":
+ position.set(Position.KEY_FUEL_CONSUMPTION, buf.readUnsignedShort() * 0.05);
+ break;
+ case "JH12":
+ buf.readUnsignedShort(); // fuel economy
+ break;
+ case "JL1":
+ position.set(Position.KEY_FUEL_USED, buf.readUnsignedInt() * 0.5);
+ break;
+ case "JL2":
+ position.set(Position.KEY_HOURS, buf.readUnsignedInt() * 5 * 36000);
+ break;
+ case "JL3":
+ position.set(Position.KEY_ODOMETER, buf.readUnsignedInt() * 1000);
+ break;
+ case "JL4":
+ position.set(Position.KEY_FUEL_USED, buf.readUnsignedInt() * 0.001);
+ break;
+ case "JS1":
+ position.set(Position.KEY_VIN, readString(buf));
+ break;
+ case "JS2":
+ readString(buf); // fms version supported
+ break;
+ case "JS3":
+ position.set("driver1", readString(buf));
+ break;
+ case "JS4":
+ position.set("driver2", readString(buf));
+ break;
+ case "JN1":
+ buf.readUnsignedInt(); // cruise control distance
+ break;
+ case "JN2":
+ buf.readUnsignedInt(); // excessive idling time
+ break;
+ case "JN3":
+ buf.readUnsignedInt(); // excessive idling fuel
+ break;
+ case "JN4":
+ buf.readUnsignedInt(); // pto time
+ break;
+ case "JN5":
+ buf.readUnsignedInt(); // pto fuel
+ break;
+ case "IN0":
+ position.set(Position.KEY_IGNITION, buf.readUnsignedByte() > 0);
+ break;
+ case "IN1":
+ case "IN2":
+ case "IN3":
+ position.set(Position.PREFIX_IN + key.charAt(2), buf.readUnsignedByte() > 0);
+ break;
+ case "HA":
+ position.set(Position.KEY_ALARM, buf.readUnsignedByte() > 0 ? Position.ALARM_ACCELERATION : null);
+ break;
+ case "HB":
+ position.set(Position.KEY_ALARM, buf.readUnsignedByte() > 0 ? Position.ALARM_BRAKING : null);
+ break;
+ case "HC":
+ position.set(Position.KEY_ALARM, buf.readUnsignedByte() > 0 ? Position.ALARM_CORNERING : null);
+ break;
default:
break;
}
diff --git a/src/main/java/org/traccar/protocol/AuroProtocol.java b/src/main/java/org/traccar/protocol/AuroProtocol.java
index d37884c8b..728c8e23c 100644
--- a/src/main/java/org/traccar/protocol/AuroProtocol.java
+++ b/src/main/java/org/traccar/protocol/AuroProtocol.java
@@ -23,7 +23,7 @@ import org.traccar.PipelineBuilder;
import org.traccar.TrackerServer;
import org.traccar.config.Config;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class AuroProtocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/AustinNbProtocol.java b/src/main/java/org/traccar/protocol/AustinNbProtocol.java
index 6a68467e2..467deff53 100644
--- a/src/main/java/org/traccar/protocol/AustinNbProtocol.java
+++ b/src/main/java/org/traccar/protocol/AustinNbProtocol.java
@@ -22,7 +22,7 @@ import org.traccar.PipelineBuilder;
import org.traccar.TrackerServer;
import org.traccar.config.Config;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class AustinNbProtocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/AutoFonProtocol.java b/src/main/java/org/traccar/protocol/AutoFonProtocol.java
index 0566b1da6..75bd28d5e 100644
--- a/src/main/java/org/traccar/protocol/AutoFonProtocol.java
+++ b/src/main/java/org/traccar/protocol/AutoFonProtocol.java
@@ -20,7 +20,7 @@ import org.traccar.PipelineBuilder;
import org.traccar.TrackerServer;
import org.traccar.config.Config;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class AutoFonProtocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/AutoGradeProtocol.java b/src/main/java/org/traccar/protocol/AutoGradeProtocol.java
index bc80e473a..69d9fb4e6 100644
--- a/src/main/java/org/traccar/protocol/AutoGradeProtocol.java
+++ b/src/main/java/org/traccar/protocol/AutoGradeProtocol.java
@@ -23,7 +23,7 @@ import org.traccar.PipelineBuilder;
import org.traccar.TrackerServer;
import org.traccar.config.Config;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class AutoGradeProtocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/AutoTrackProtocol.java b/src/main/java/org/traccar/protocol/AutoTrackProtocol.java
index 80255d3e9..df489de3c 100644
--- a/src/main/java/org/traccar/protocol/AutoTrackProtocol.java
+++ b/src/main/java/org/traccar/protocol/AutoTrackProtocol.java
@@ -22,7 +22,7 @@ import org.traccar.TrackerServer;
import org.traccar.config.Config;
import java.nio.ByteOrder;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class AutoTrackProtocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/AvemaProtocol.java b/src/main/java/org/traccar/protocol/AvemaProtocol.java
index b35a447ff..0eeee41b8 100644
--- a/src/main/java/org/traccar/protocol/AvemaProtocol.java
+++ b/src/main/java/org/traccar/protocol/AvemaProtocol.java
@@ -23,7 +23,7 @@ import org.traccar.PipelineBuilder;
import org.traccar.TrackerServer;
import org.traccar.config.Config;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class AvemaProtocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/Avl301Protocol.java b/src/main/java/org/traccar/protocol/Avl301Protocol.java
index c4a0affdc..452bc1501 100644
--- a/src/main/java/org/traccar/protocol/Avl301Protocol.java
+++ b/src/main/java/org/traccar/protocol/Avl301Protocol.java
@@ -21,7 +21,7 @@ import org.traccar.PipelineBuilder;
import org.traccar.TrackerServer;
import org.traccar.config.Config;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class Avl301Protocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/B2316Protocol.java b/src/main/java/org/traccar/protocol/B2316Protocol.java
index 582be0b56..e0a6821d8 100644
--- a/src/main/java/org/traccar/protocol/B2316Protocol.java
+++ b/src/main/java/org/traccar/protocol/B2316Protocol.java
@@ -22,7 +22,7 @@ import org.traccar.PipelineBuilder;
import org.traccar.TrackerServer;
import org.traccar.config.Config;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class B2316Protocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/B2316ProtocolDecoder.java b/src/main/java/org/traccar/protocol/B2316ProtocolDecoder.java
index 635806b2d..b0a5411f7 100644
--- a/src/main/java/org/traccar/protocol/B2316ProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/B2316ProtocolDecoder.java
@@ -24,9 +24,9 @@ import org.traccar.model.Network;
import org.traccar.model.Position;
import org.traccar.model.WifiAccessPoint;
-import javax.json.Json;
-import javax.json.JsonArray;
-import javax.json.JsonObject;
+import jakarta.json.Json;
+import jakarta.json.JsonArray;
+import jakarta.json.JsonObject;
import java.io.StringReader;
import java.net.SocketAddress;
import java.util.Date;
diff --git a/src/main/java/org/traccar/protocol/BceProtocol.java b/src/main/java/org/traccar/protocol/BceProtocol.java
index 31fb1bd83..5e1c10abc 100644
--- a/src/main/java/org/traccar/protocol/BceProtocol.java
+++ b/src/main/java/org/traccar/protocol/BceProtocol.java
@@ -21,7 +21,7 @@ import org.traccar.TrackerServer;
import org.traccar.config.Config;
import org.traccar.model.Command;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class BceProtocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/BlackKiteProtocol.java b/src/main/java/org/traccar/protocol/BlackKiteProtocol.java
index 3859a9273..d584af5a1 100644
--- a/src/main/java/org/traccar/protocol/BlackKiteProtocol.java
+++ b/src/main/java/org/traccar/protocol/BlackKiteProtocol.java
@@ -21,7 +21,7 @@ import org.traccar.PipelineBuilder;
import org.traccar.TrackerServer;
import org.traccar.config.Config;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class BlackKiteProtocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/BlueProtocol.java b/src/main/java/org/traccar/protocol/BlueProtocol.java
index da195f438..821111ad7 100644
--- a/src/main/java/org/traccar/protocol/BlueProtocol.java
+++ b/src/main/java/org/traccar/protocol/BlueProtocol.java
@@ -21,7 +21,7 @@ import org.traccar.PipelineBuilder;
import org.traccar.TrackerServer;
import org.traccar.config.Config;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class BlueProtocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/BoxProtocol.java b/src/main/java/org/traccar/protocol/BoxProtocol.java
index dc6852d50..ac1ba7cae 100644
--- a/src/main/java/org/traccar/protocol/BoxProtocol.java
+++ b/src/main/java/org/traccar/protocol/BoxProtocol.java
@@ -23,7 +23,7 @@ import org.traccar.PipelineBuilder;
import org.traccar.TrackerServer;
import org.traccar.config.Config;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class BoxProtocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/BstplProtocol.java b/src/main/java/org/traccar/protocol/BstplProtocol.java
index dde14a2ca..ccedcf3d9 100644
--- a/src/main/java/org/traccar/protocol/BstplProtocol.java
+++ b/src/main/java/org/traccar/protocol/BstplProtocol.java
@@ -23,7 +23,7 @@ import org.traccar.PipelineBuilder;
import org.traccar.TrackerServer;
import org.traccar.config.Config;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class BstplProtocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/C2stekProtocol.java b/src/main/java/org/traccar/protocol/C2stekProtocol.java
index 5cd8ef4fd..5370ea762 100644
--- a/src/main/java/org/traccar/protocol/C2stekProtocol.java
+++ b/src/main/java/org/traccar/protocol/C2stekProtocol.java
@@ -23,7 +23,7 @@ import org.traccar.PipelineBuilder;
import org.traccar.TrackerServer;
import org.traccar.config.Config;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class C2stekProtocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/CalAmpProtocol.java b/src/main/java/org/traccar/protocol/CalAmpProtocol.java
index d67308cf2..06df6e196 100644
--- a/src/main/java/org/traccar/protocol/CalAmpProtocol.java
+++ b/src/main/java/org/traccar/protocol/CalAmpProtocol.java
@@ -20,7 +20,7 @@ import org.traccar.PipelineBuilder;
import org.traccar.TrackerServer;
import org.traccar.config.Config;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class CalAmpProtocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/CarTrackProtocol.java b/src/main/java/org/traccar/protocol/CarTrackProtocol.java
index 0538aad72..366f32034 100644
--- a/src/main/java/org/traccar/protocol/CarTrackProtocol.java
+++ b/src/main/java/org/traccar/protocol/CarTrackProtocol.java
@@ -23,7 +23,7 @@ import org.traccar.PipelineBuilder;
import org.traccar.TrackerServer;
import org.traccar.config.Config;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class CarTrackProtocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/CarcellProtocol.java b/src/main/java/org/traccar/protocol/CarcellProtocol.java
index 832d9bb2d..7ae8159d5 100644
--- a/src/main/java/org/traccar/protocol/CarcellProtocol.java
+++ b/src/main/java/org/traccar/protocol/CarcellProtocol.java
@@ -24,7 +24,7 @@ import org.traccar.TrackerServer;
import org.traccar.config.Config;
import org.traccar.model.Command;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class CarcellProtocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/CarscopProtocol.java b/src/main/java/org/traccar/protocol/CarscopProtocol.java
index a4413af28..e904c01c5 100644
--- a/src/main/java/org/traccar/protocol/CarscopProtocol.java
+++ b/src/main/java/org/traccar/protocol/CarscopProtocol.java
@@ -23,7 +23,7 @@ import org.traccar.PipelineBuilder;
import org.traccar.TrackerServer;
import org.traccar.config.Config;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class CarscopProtocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/CastelProtocol.java b/src/main/java/org/traccar/protocol/CastelProtocol.java
index 9323b1503..74a9e9ca1 100644
--- a/src/main/java/org/traccar/protocol/CastelProtocol.java
+++ b/src/main/java/org/traccar/protocol/CastelProtocol.java
@@ -23,7 +23,7 @@ import org.traccar.config.Config;
import org.traccar.model.Command;
import java.nio.ByteOrder;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class CastelProtocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/CastelProtocolDecoder.java b/src/main/java/org/traccar/protocol/CastelProtocolDecoder.java
index 4aa65245b..b076b9f66 100644
--- a/src/main/java/org/traccar/protocol/CastelProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/CastelProtocolDecoder.java
@@ -16,7 +16,6 @@
package org.traccar.protocol;
import io.netty.buffer.ByteBuf;
-import io.netty.buffer.ByteBufUtil;
import io.netty.buffer.Unpooled;
import io.netty.channel.Channel;
import org.traccar.BaseProtocolDecoder;
@@ -284,15 +283,27 @@ public class CastelProtocolDecoder extends BaseProtocolDecoder {
case 0x0C:
position.set(Position.KEY_ALARM, Position.ALARM_CORNERING);
break;
+ case 0x0D:
+ position.set(Position.KEY_ALARM, Position.ALARM_FATIGUE_DRIVING);
+ break;
case 0x0E:
position.set(Position.KEY_ALARM, Position.ALARM_POWER_OFF);
break;
+ case 0x11:
+ position.set(Position.KEY_ALARM, Position.ALARM_ACCIDENT);
+ break;
+ case 0x12:
+ position.set(Position.KEY_ALARM, Position.ALARM_TAMPERING);
+ break;
case 0x16:
position.set(Position.KEY_IGNITION, true);
break;
case 0x17:
position.set(Position.KEY_IGNITION, false);
break;
+ case 0x1C:
+ position.set(Position.KEY_ALARM, Position.ALARM_VIBRATION);
+ break;
default:
break;
}
@@ -359,9 +370,9 @@ public class CastelProtocolDecoder extends BaseProtocolDecoder {
int alarmCount = buf.readUnsignedByte();
for (int i = 0; i < alarmCount; i++) {
if (buf.readUnsignedByte() != 0) {
- int alarm = buf.readUnsignedByte();
+ int event = buf.readUnsignedByte();
for (Position p : positions) {
- decodeAlarm(p, alarm);
+ decodeAlarm(p, event);
}
buf.readUnsignedShortLE(); // description
buf.readUnsignedShortLE(); // threshold
@@ -421,12 +432,26 @@ public class CastelProtocolDecoder extends BaseProtocolDecoder {
return position;
case MSG_SC_DTCS_PASSENGER:
+ case MSG_SC_DTCS_COMMERCIAL:
position = createPosition(deviceSession);
decodeStat(position, buf);
buf.readUnsignedByte(); // flag
- position.add(ObdDecoder.decodeCodes(ByteBufUtil.hexDump(buf.readSlice(buf.readUnsignedByte()))));
+
+ count = buf.readUnsignedByte();
+ StringBuilder codes = new StringBuilder();
+ for (int i = 0; i < count; i++) {
+ if (type == MSG_SC_DTCS_COMMERCIAL) {
+ codes.append(ObdDecoder.decodeCode(buf.readUnsignedShortLE()));
+ buf.readUnsignedByte(); // attribute
+ buf.readUnsignedByte(); // occurrence
+ } else {
+ codes.append(ObdDecoder.decodeCode(buf.readUnsignedShortLE()));
+ }
+ codes.append(' ');
+ }
+ position.set(Position.KEY_DTCS, codes.toString().trim());
return position;
diff --git a/src/main/java/org/traccar/protocol/CautelaProtocol.java b/src/main/java/org/traccar/protocol/CautelaProtocol.java
index d0ca35ef1..067345f49 100644
--- a/src/main/java/org/traccar/protocol/CautelaProtocol.java
+++ b/src/main/java/org/traccar/protocol/CautelaProtocol.java
@@ -23,7 +23,7 @@ import org.traccar.PipelineBuilder;
import org.traccar.TrackerServer;
import org.traccar.config.Config;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class CautelaProtocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/CellocatorProtocol.java b/src/main/java/org/traccar/protocol/CellocatorProtocol.java
index 3287928c7..e3325c8b7 100644
--- a/src/main/java/org/traccar/protocol/CellocatorProtocol.java
+++ b/src/main/java/org/traccar/protocol/CellocatorProtocol.java
@@ -21,7 +21,7 @@ import org.traccar.TrackerServer;
import org.traccar.config.Config;
import org.traccar.model.Command;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class CellocatorProtocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/CguardProtocol.java b/src/main/java/org/traccar/protocol/CguardProtocol.java
index caf0aad42..c0fc9582a 100644
--- a/src/main/java/org/traccar/protocol/CguardProtocol.java
+++ b/src/main/java/org/traccar/protocol/CguardProtocol.java
@@ -23,7 +23,7 @@ import org.traccar.PipelineBuilder;
import org.traccar.TrackerServer;
import org.traccar.config.Config;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class CguardProtocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/CityeasyProtocol.java b/src/main/java/org/traccar/protocol/CityeasyProtocol.java
index 9656b284b..60ed5d135 100644
--- a/src/main/java/org/traccar/protocol/CityeasyProtocol.java
+++ b/src/main/java/org/traccar/protocol/CityeasyProtocol.java
@@ -22,7 +22,7 @@ import org.traccar.TrackerServer;
import org.traccar.config.Config;
import org.traccar.model.Command;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class CityeasyProtocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/ContinentalProtocol.java b/src/main/java/org/traccar/protocol/ContinentalProtocol.java
index 06e93d79d..9567374fd 100644
--- a/src/main/java/org/traccar/protocol/ContinentalProtocol.java
+++ b/src/main/java/org/traccar/protocol/ContinentalProtocol.java
@@ -21,7 +21,7 @@ import org.traccar.PipelineBuilder;
import org.traccar.TrackerServer;
import org.traccar.config.Config;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class ContinentalProtocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/CradlepointProtocol.java b/src/main/java/org/traccar/protocol/CradlepointProtocol.java
index 7f201a31d..220db0747 100644
--- a/src/main/java/org/traccar/protocol/CradlepointProtocol.java
+++ b/src/main/java/org/traccar/protocol/CradlepointProtocol.java
@@ -23,7 +23,7 @@ import org.traccar.PipelineBuilder;
import org.traccar.TrackerServer;
import org.traccar.config.Config;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class CradlepointProtocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/DingtekProtocol.java b/src/main/java/org/traccar/protocol/DingtekProtocol.java
index e9466b7e8..ab3e32fdb 100644
--- a/src/main/java/org/traccar/protocol/DingtekProtocol.java
+++ b/src/main/java/org/traccar/protocol/DingtekProtocol.java
@@ -22,7 +22,7 @@ import org.traccar.PipelineBuilder;
import org.traccar.TrackerServer;
import org.traccar.config.Config;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class DingtekProtocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/DishaProtocol.java b/src/main/java/org/traccar/protocol/DishaProtocol.java
index f83b8349a..0a582731d 100644
--- a/src/main/java/org/traccar/protocol/DishaProtocol.java
+++ b/src/main/java/org/traccar/protocol/DishaProtocol.java
@@ -23,7 +23,7 @@ import org.traccar.PipelineBuilder;
import org.traccar.TrackerServer;
import org.traccar.config.Config;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class DishaProtocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/DmtHttpProtocol.java b/src/main/java/org/traccar/protocol/DmtHttpProtocol.java
index 0dab26cda..d15bfa1ca 100644
--- a/src/main/java/org/traccar/protocol/DmtHttpProtocol.java
+++ b/src/main/java/org/traccar/protocol/DmtHttpProtocol.java
@@ -23,7 +23,7 @@ import org.traccar.PipelineBuilder;
import org.traccar.TrackerServer;
import org.traccar.config.Config;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class DmtHttpProtocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/DmtHttpProtocolDecoder.java b/src/main/java/org/traccar/protocol/DmtHttpProtocolDecoder.java
index 807850778..c2e617a2a 100644
--- a/src/main/java/org/traccar/protocol/DmtHttpProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/DmtHttpProtocolDecoder.java
@@ -25,9 +25,9 @@ import org.traccar.helper.BitUtil;
import org.traccar.helper.UnitsConverter;
import org.traccar.model.Position;
-import javax.json.Json;
-import javax.json.JsonArray;
-import javax.json.JsonObject;
+import jakarta.json.Json;
+import jakarta.json.JsonArray;
+import jakarta.json.JsonObject;
import java.io.StringReader;
import java.net.SocketAddress;
import java.nio.charset.StandardCharsets;
diff --git a/src/main/java/org/traccar/protocol/DmtProtocol.java b/src/main/java/org/traccar/protocol/DmtProtocol.java
index de56c9372..e89920cd3 100644
--- a/src/main/java/org/traccar/protocol/DmtProtocol.java
+++ b/src/main/java/org/traccar/protocol/DmtProtocol.java
@@ -22,7 +22,7 @@ import org.traccar.TrackerServer;
import org.traccar.config.Config;
import java.nio.ByteOrder;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class DmtProtocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/DolphinProtocol.java b/src/main/java/org/traccar/protocol/DolphinProtocol.java
index ed627be78..e2acce7dd 100644
--- a/src/main/java/org/traccar/protocol/DolphinProtocol.java
+++ b/src/main/java/org/traccar/protocol/DolphinProtocol.java
@@ -23,7 +23,7 @@ import org.traccar.config.Config;
import java.nio.ByteOrder;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class DolphinProtocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/DraginoProtocol.java b/src/main/java/org/traccar/protocol/DraginoProtocol.java
new file mode 100644
index 000000000..d33efe2ad
--- /dev/null
+++ b/src/main/java/org/traccar/protocol/DraginoProtocol.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2023 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.http.HttpObjectAggregator;
+import io.netty.handler.codec.http.HttpRequestDecoder;
+import io.netty.handler.codec.http.HttpResponseEncoder;
+import jakarta.inject.Inject;
+import org.traccar.BaseProtocol;
+import org.traccar.PipelineBuilder;
+import org.traccar.TrackerServer;
+import org.traccar.config.Config;
+
+public class DraginoProtocol extends BaseProtocol {
+
+ @Inject
+ public DraginoProtocol(Config config) {
+ addServer(new TrackerServer(config, getName(), false) {
+ @Override
+ protected void addProtocolHandlers(PipelineBuilder pipeline, Config config) {
+ pipeline.addLast(new HttpResponseEncoder());
+ pipeline.addLast(new HttpRequestDecoder());
+ pipeline.addLast(new HttpObjectAggregator(65535));
+ pipeline.addLast(new DraginoProtocolDecoder(DraginoProtocol.this));
+ }
+ });
+ }
+
+}
diff --git a/src/main/java/org/traccar/protocol/DraginoProtocolDecoder.java b/src/main/java/org/traccar/protocol/DraginoProtocolDecoder.java
new file mode 100644
index 000000000..5f576d723
--- /dev/null
+++ b/src/main/java/org/traccar/protocol/DraginoProtocolDecoder.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright 2023 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 io.netty.handler.codec.http.FullHttpRequest;
+import io.netty.handler.codec.http.HttpResponseStatus;
+import jakarta.json.Json;
+import jakarta.json.JsonObject;
+import org.traccar.BaseHttpProtocolDecoder;
+import org.traccar.Protocol;
+import org.traccar.helper.DateUtil;
+import org.traccar.model.Position;
+import org.traccar.session.DeviceSession;
+
+import java.io.StringReader;
+import java.net.SocketAddress;
+import java.nio.charset.StandardCharsets;
+
+public class DraginoProtocolDecoder extends BaseHttpProtocolDecoder {
+
+ public DraginoProtocolDecoder(Protocol protocol) {
+ super(protocol);
+ }
+
+ @Override
+ protected Object decode(
+ Channel channel, SocketAddress remoteAddress, Object msg) throws Exception {
+
+ FullHttpRequest request = (FullHttpRequest) msg;
+ String content = request.content().toString(StandardCharsets.UTF_8);
+ JsonObject json = Json.createReader(new StringReader(content)).readObject();
+
+ String deviceId = json.getJsonObject("end_device_ids").getString("device_id");
+ DeviceSession deviceSession = getDeviceSession(channel, remoteAddress, deviceId);
+ if (deviceSession == null) {
+ sendResponse(channel, HttpResponseStatus.BAD_REQUEST);
+ return null;
+ }
+
+ JsonObject message = json.getJsonObject("uplink_message");
+ JsonObject decoded = message.getJsonObject("decoded_payload");
+
+ Position position = new Position(getProtocolName());
+ position.setDeviceId(deviceSession.getDeviceId());
+
+ position.setTime(DateUtil.parseDate(message.getString("received_at")));
+
+ position.setValid(true);
+ position.setLatitude(decoded.getJsonNumber("Latitude").doubleValue());
+ position.setLongitude(decoded.getJsonNumber("Longitude").doubleValue());
+
+ position.set("humidity", decoded.getJsonNumber("Hum").doubleValue());
+ position.set(Position.KEY_BATTERY, decoded.getJsonNumber("BatV").doubleValue());
+ position.set(Position.PREFIX_TEMP + 1, decoded.getJsonNumber("Tem").doubleValue());
+
+ if (Boolean.parseBoolean(decoded.getString("ALARM_status"))) {
+ position.set(Position.KEY_ALARM, Position.ALARM_SOS);
+ }
+
+ sendResponse(channel, HttpResponseStatus.OK);
+ return position;
+ }
+
+}
diff --git a/src/main/java/org/traccar/protocol/Dsf22Protocol.java b/src/main/java/org/traccar/protocol/Dsf22Protocol.java
index 06c99b0f9..ad349a7ff 100644
--- a/src/main/java/org/traccar/protocol/Dsf22Protocol.java
+++ b/src/main/java/org/traccar/protocol/Dsf22Protocol.java
@@ -20,7 +20,7 @@ import org.traccar.PipelineBuilder;
import org.traccar.TrackerServer;
import org.traccar.config.Config;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class Dsf22Protocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/DualcamProtocol.java b/src/main/java/org/traccar/protocol/DualcamProtocol.java
index 363a2c5d9..4725cb180 100644
--- a/src/main/java/org/traccar/protocol/DualcamProtocol.java
+++ b/src/main/java/org/traccar/protocol/DualcamProtocol.java
@@ -20,7 +20,7 @@ import org.traccar.PipelineBuilder;
import org.traccar.TrackerServer;
import org.traccar.config.Config;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class DualcamProtocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/DualcamProtocolDecoder.java b/src/main/java/org/traccar/protocol/DualcamProtocolDecoder.java
index d03f7648d..411e2b9d7 100644
--- a/src/main/java/org/traccar/protocol/DualcamProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/DualcamProtocolDecoder.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2021 - 2022 Anton Tananaev (anton@traccar.org)
+ * Copyright 2021 - 2023 Anton Tananaev (anton@traccar.org)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -42,13 +42,24 @@ public class DualcamProtocolDecoder extends BaseProtocolDecoder {
public static final int MSG_COMPLETE = 5;
public static final int MSG_FILE_REQUEST = 8;
public static final int MSG_INIT_REQUEST = 9;
+ public static final int MSG_PATH_REQUEST = 0x000C;
+ public static final int MSG_PATH_RESPONSE = 0x000D;
+ private String model;
private String uniqueId;
- private int packetCount;
- private int currentPacket;
+ private int dataSize;
+ private int dataCurrent;
private boolean video;
private ByteBuf media;
+ private boolean isPacketData() {
+ if (model == null) {
+ return dataSize < 8192;
+ } else {
+ return !"DSM".equals(model);
+ }
+ }
+
@Override
protected Object decode(
Channel channel, SocketAddress remoteAddress, Object msg) throws Exception {
@@ -57,15 +68,21 @@ public class DualcamProtocolDecoder extends BaseProtocolDecoder {
int type = buf.readUnsignedShort();
+ DeviceSession deviceSession;
switch (type) {
case MSG_INIT:
buf.readUnsignedShort(); // protocol id
uniqueId = String.valueOf(buf.readLong());
- DeviceSession deviceSession = getDeviceSession(channel, remoteAddress, uniqueId);
+ deviceSession = getDeviceSession(channel, remoteAddress, uniqueId);
long settings = buf.readUnsignedInt();
if (channel != null && deviceSession != null) {
+ model = getDeviceModel(deviceSession);
ByteBuf response = Unpooled.buffer();
- if (BitUtil.between(settings, 26, 30) > 0) {
+ if (BitUtil.check(settings, 25)) {
+ response.writeShort(MSG_PATH_REQUEST);
+ response.writeShort(2);
+ response.writeShort(0);
+ } else if (BitUtil.between(settings, 26, 30) > 0) {
response.writeShort(MSG_FILE_REQUEST);
String file;
if (BitUtil.check(settings, 26)) {
@@ -91,21 +108,29 @@ public class DualcamProtocolDecoder extends BaseProtocolDecoder {
break;
case MSG_START:
buf.readUnsignedShort(); // length
- packetCount = buf.readInt();
- currentPacket = 1;
+ dataSize = buf.readInt();
+ dataCurrent = isPacketData() ? 1 : 0;
media = Unpooled.buffer();
if (channel != null) {
ByteBuf response = Unpooled.buffer();
response.writeShort(MSG_RESUME);
response.writeShort(4);
- response.writeInt(currentPacket);
+ response.writeInt(dataCurrent);
channel.writeAndFlush(new NetworkMessage(response, remoteAddress));
}
break;
case MSG_DATA:
- buf.readUnsignedShort(); // length
- media.writeBytes(buf, buf.readableBytes() - 2);
- if (currentPacket == packetCount) {
+ int length = buf.readUnsignedShort() - 2;
+ media.writeBytes(buf, length);
+ boolean finished;
+ if (isPacketData()) {
+ finished = dataCurrent == dataSize;
+ dataCurrent += 1;
+ } else {
+ finished = dataCurrent + length == dataSize;
+ dataCurrent += length;
+ }
+ if (finished) {
deviceSession = getDeviceSession(channel, remoteAddress);
Position position = new Position(getProtocolName());
position.setDeviceId(deviceSession.getDeviceId());
@@ -126,8 +151,16 @@ public class DualcamProtocolDecoder extends BaseProtocolDecoder {
channel.writeAndFlush(new NetworkMessage(response, remoteAddress));
}
return position;
- } else {
- currentPacket += 1;
+ }
+ break;
+ case MSG_PATH_RESPONSE:
+ String file = buf.readCharSequence(buf.readUnsignedShort(), StandardCharsets.US_ASCII).toString();
+ if (channel != null) {
+ ByteBuf response = Unpooled.buffer();
+ response.writeShort(MSG_FILE_REQUEST);
+ response.writeShort(file.length());
+ response.writeCharSequence(file, StandardCharsets.US_ASCII);
+ channel.writeAndFlush(new NetworkMessage(response, remoteAddress));
}
break;
default:
diff --git a/src/main/java/org/traccar/protocol/DwayProtocol.java b/src/main/java/org/traccar/protocol/DwayProtocol.java
index 1096c945c..2ba1cf5f1 100644
--- a/src/main/java/org/traccar/protocol/DwayProtocol.java
+++ b/src/main/java/org/traccar/protocol/DwayProtocol.java
@@ -23,7 +23,7 @@ import org.traccar.PipelineBuilder;
import org.traccar.TrackerServer;
import org.traccar.config.Config;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class DwayProtocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/EasyTrackProtocol.java b/src/main/java/org/traccar/protocol/EasyTrackProtocol.java
index 39aa61580..25d4ef9a0 100644
--- a/src/main/java/org/traccar/protocol/EasyTrackProtocol.java
+++ b/src/main/java/org/traccar/protocol/EasyTrackProtocol.java
@@ -24,7 +24,7 @@ import org.traccar.TrackerServer;
import org.traccar.config.Config;
import org.traccar.model.Command;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class EasyTrackProtocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/EasyTrackProtocolDecoder.java b/src/main/java/org/traccar/protocol/EasyTrackProtocolDecoder.java
index 805cf1197..b10ff4c64 100644
--- a/src/main/java/org/traccar/protocol/EasyTrackProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/EasyTrackProtocolDecoder.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2013 - 2021 Anton Tananaev (anton@traccar.org)
+ * Copyright 2013 - 2023 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.
@@ -79,26 +79,45 @@ public class EasyTrackProtocolDecoder extends BaseProtocolDecoder {
.any()
.compile();
+ private static final Pattern PATTERN_OBD = new PatternBuilder()
+ .text("*").expression("..,") // manufacturer
+ .number("(d+),") // imei
+ .text("OB,") // command
+ .text("BD$")
+ .number("V(d+.d);") // battery
+ .number("R(d+);") // rpm
+ .number("S(d+);") // speed
+ .number("P(d+.d);") // throttle
+ .number("O(d+.d);") // engine load
+ .number("C(d+);") // coolant temperature
+ .number("L(d+.d);") // fuel level
+ .number("[XY][MH]d+.d+;")
+ .number("M(d+);") // mileage
+ .number("F(d+.d+);") // fuel consumption
+ .number("T(d+);") // engine time
+ .any()
+ .compile();
+
private String decodeAlarm(long status) {
- if ((status & 0x02000000) != 0) {
+ if ((status & 0x02000000L) != 0) {
return Position.ALARM_GEOFENCE_ENTER;
}
- if ((status & 0x04000000) != 0) {
+ if ((status & 0x04000000L) != 0) {
return Position.ALARM_GEOFENCE_EXIT;
}
- if ((status & 0x08000000) != 0) {
+ if ((status & 0x08000000L) != 0) {
return Position.ALARM_LOW_BATTERY;
}
- if ((status & 0x20000000) != 0) {
+ if ((status & 0x20000000L) != 0) {
return Position.ALARM_VIBRATION;
}
- if ((status & 0x80000000) != 0) {
+ if ((status & 0x80000000L) != 0) {
return Position.ALARM_OVERSPEED;
}
- if ((status & 0x00010000) != 0) {
+ if ((status & 0x00010000L) != 0) {
return Position.ALARM_SOS;
}
- if ((status & 0x00040000) != 0) {
+ if ((status & 0x00040000L) != 0) {
return Position.ALARM_POWER_CUT;
}
return null;
@@ -115,7 +134,9 @@ public class EasyTrackProtocolDecoder extends BaseProtocolDecoder {
channel.writeAndFlush(new NetworkMessage(sentence + "#", remoteAddress));
}
- if (type.equals("JZ")) {
+ if (type.equals("OB")) {
+ return decodeObd(channel, remoteAddress, sentence);
+ } else if (type.equals("JZ")) {
return decodeCell(channel, remoteAddress, sentence);
} else {
return decodeLocation(channel, remoteAddress, sentence);
@@ -219,4 +240,35 @@ public class EasyTrackProtocolDecoder extends BaseProtocolDecoder {
return position;
}
+ private Position decodeObd(Channel channel, SocketAddress remoteAddress, String sentence) {
+
+ Parser parser = new Parser(PATTERN_OBD, sentence);
+ 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());
+
+ getLastLocation(position, null);
+
+ position.set(Position.KEY_BATTERY, parser.nextDouble());
+ position.set(Position.KEY_RPM, parser.nextInt());
+ position.set(Position.KEY_OBD_SPEED, parser.nextInt());
+ position.set(Position.KEY_THROTTLE, parser.nextDouble());
+ position.set(Position.KEY_ENGINE_LOAD, parser.nextDouble());
+ position.set(Position.KEY_COOLANT_TEMP, parser.nextInt());
+ position.set(Position.KEY_FUEL_LEVEL, parser.nextDouble());
+ position.set(Position.KEY_ODOMETER, parser.nextInt());
+ position.set(Position.KEY_FUEL_CONSUMPTION, parser.nextDouble());
+ position.set(Position.KEY_HOURS, parser.nextInt());
+
+ return position;
+ }
+
}
diff --git a/src/main/java/org/traccar/protocol/EelinkProtocol.java b/src/main/java/org/traccar/protocol/EelinkProtocol.java
index 35fd4fe65..2a3c0bd15 100644
--- a/src/main/java/org/traccar/protocol/EelinkProtocol.java
+++ b/src/main/java/org/traccar/protocol/EelinkProtocol.java
@@ -22,7 +22,7 @@ import org.traccar.TrackerServer;
import org.traccar.config.Config;
import org.traccar.model.Command;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class EelinkProtocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/EelinkProtocolDecoder.java b/src/main/java/org/traccar/protocol/EelinkProtocolDecoder.java
index cb0e10042..db1b365c3 100644
--- a/src/main/java/org/traccar/protocol/EelinkProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/EelinkProtocolDecoder.java
@@ -314,7 +314,7 @@ public class EelinkProtocolDecoder extends BaseProtocolDecoder {
}
if (buf.readableBytes() >= 12) {
- position.set(Position.PREFIX_TEMP + 1, buf.readUnsignedShort() / 256.0);
+ position.set(Position.PREFIX_TEMP + 1, buf.readShort() / 256.0);
position.set("humidity", buf.readUnsignedShort() * 0.1);
position.set("illuminance", buf.readUnsignedInt() / 256.0);
position.set("co2", buf.readUnsignedInt());
diff --git a/src/main/java/org/traccar/protocol/EgtsProtocol.java b/src/main/java/org/traccar/protocol/EgtsProtocol.java
index f257271d4..5450d9f01 100644
--- a/src/main/java/org/traccar/protocol/EgtsProtocol.java
+++ b/src/main/java/org/traccar/protocol/EgtsProtocol.java
@@ -20,7 +20,7 @@ import org.traccar.PipelineBuilder;
import org.traccar.TrackerServer;
import org.traccar.config.Config;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class EgtsProtocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/EnforaProtocol.java b/src/main/java/org/traccar/protocol/EnforaProtocol.java
index ebde56f70..3b796db25 100644
--- a/src/main/java/org/traccar/protocol/EnforaProtocol.java
+++ b/src/main/java/org/traccar/protocol/EnforaProtocol.java
@@ -22,7 +22,7 @@ import org.traccar.TrackerServer;
import org.traccar.config.Config;
import org.traccar.model.Command;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class EnforaProtocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/EnnfuProtocol.java b/src/main/java/org/traccar/protocol/EnnfuProtocol.java
index e326481fa..a3ff943fa 100644
--- a/src/main/java/org/traccar/protocol/EnnfuProtocol.java
+++ b/src/main/java/org/traccar/protocol/EnnfuProtocol.java
@@ -23,7 +23,7 @@ import org.traccar.PipelineBuilder;
import org.traccar.TrackerServer;
import org.traccar.config.Config;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class EnnfuProtocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/EnvotechProtocol.java b/src/main/java/org/traccar/protocol/EnvotechProtocol.java
index dffa1c991..e432ac07c 100644
--- a/src/main/java/org/traccar/protocol/EnvotechProtocol.java
+++ b/src/main/java/org/traccar/protocol/EnvotechProtocol.java
@@ -23,7 +23,7 @@ import org.traccar.PipelineBuilder;
import org.traccar.TrackerServer;
import org.traccar.config.Config;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class EnvotechProtocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/EsealProtocol.java b/src/main/java/org/traccar/protocol/EsealProtocol.java
index 0ed80dc6f..eae4cf2aa 100644
--- a/src/main/java/org/traccar/protocol/EsealProtocol.java
+++ b/src/main/java/org/traccar/protocol/EsealProtocol.java
@@ -24,7 +24,7 @@ import org.traccar.TrackerServer;
import org.traccar.config.Config;
import org.traccar.model.Command;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class EsealProtocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/EskyProtocol.java b/src/main/java/org/traccar/protocol/EskyProtocol.java
index cb2f59dc8..002e268ba 100644
--- a/src/main/java/org/traccar/protocol/EskyProtocol.java
+++ b/src/main/java/org/traccar/protocol/EskyProtocol.java
@@ -22,7 +22,7 @@ import org.traccar.PipelineBuilder;
import org.traccar.TrackerServer;
import org.traccar.config.Config;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class EskyProtocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/ExtremTracProtocol.java b/src/main/java/org/traccar/protocol/ExtremTracProtocol.java
index ffc941b69..23a993fe4 100644
--- a/src/main/java/org/traccar/protocol/ExtremTracProtocol.java
+++ b/src/main/java/org/traccar/protocol/ExtremTracProtocol.java
@@ -23,7 +23,7 @@ import org.traccar.PipelineBuilder;
import org.traccar.TrackerServer;
import org.traccar.config.Config;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class ExtremTracProtocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/FifotrackProtocol.java b/src/main/java/org/traccar/protocol/FifotrackProtocol.java
index fd2beaabb..e98ad84cc 100644
--- a/src/main/java/org/traccar/protocol/FifotrackProtocol.java
+++ b/src/main/java/org/traccar/protocol/FifotrackProtocol.java
@@ -22,7 +22,7 @@ import org.traccar.TrackerServer;
import org.traccar.config.Config;
import org.traccar.model.Command;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class FifotrackProtocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/FifotrackProtocolDecoder.java b/src/main/java/org/traccar/protocol/FifotrackProtocolDecoder.java
index a9d77b46e..59019830f 100644
--- a/src/main/java/org/traccar/protocol/FifotrackProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/FifotrackProtocolDecoder.java
@@ -64,7 +64,7 @@ public class FifotrackProtocolDecoder extends BaseProtocolDecoder {
.number("(d+),") // course
.number("(-?d+),") // altitude
.number("(d+),") // odometer
- .number("d+,") // runtime
+ .number("(d+),") // engine hours
.number("(x+),") // status
.number("(x+)?,") // input
.number("(x+)?,") // output
@@ -183,6 +183,8 @@ public class FifotrackProtocolDecoder extends BaseProtocolDecoder {
case 30:
case 32:
return Position.ALARM_JAMMING;
+ case 31:
+ return Position.ALARM_FALL_DOWN;
case 33:
return Position.ALARM_GEOFENCE_EXIT;
case 34:
@@ -192,6 +194,10 @@ public class FifotrackProtocolDecoder extends BaseProtocolDecoder {
case 40:
case 41:
return Position.ALARM_TEMPERATURE;
+ case 53:
+ return Position.ALARM_POWER_ON;
+ case 54:
+ return Position.ALARM_POWER_OFF;
default:
return null;
}
@@ -235,13 +241,15 @@ public class FifotrackProtocolDecoder extends BaseProtocolDecoder {
position.setValid(parser.next().equals("A"));
position.setFixTime(position.getDeviceTime());
- position.set(Position.KEY_SATELLITES, parser.nextInt());
position.setSpeed(UnitsConverter.knotsFromKph(parser.nextInt()));
+ position.set(Position.KEY_SATELLITES, parser.nextInt());
position.setLatitude(parser.nextDouble());
position.setLongitude(parser.nextDouble());
} else {
+ getLastLocation(position, position.getDeviceTime());
+
String[] points = parser.next().split("\\|");
for (String point : points) {
String[] wifi = point.split(":");
@@ -290,6 +298,7 @@ public class FifotrackProtocolDecoder extends BaseProtocolDecoder {
position.setAltitude(parser.nextInt());
position.set(Position.KEY_ODOMETER, parser.nextLong());
+ position.set(Position.KEY_HOURS, parser.nextLong() * 1000);
long status = parser.nextHexLong();
position.set(Position.KEY_RSSI, BitUtil.between(status, 3, 8));
@@ -308,11 +317,11 @@ public class FifotrackProtocolDecoder extends BaseProtocolDecoder {
}
if (parser.hasNext()) {
- String rfid = parser.next();
- if (rfid.matches("\\p{XDigit}+")) {
- position.set(Position.KEY_DRIVER_UNIQUE_ID, String.valueOf(Integer.parseInt(rfid, 16)));
+ String value = parser.next();
+ if (value.matches("\\p{XDigit}+")) {
+ position.set(Position.KEY_DRIVER_UNIQUE_ID, String.valueOf(Integer.parseInt(value, 16)));
} else {
- position.set("driverLicense", rfid);
+ position.set(Position.KEY_CARD, value);
}
}
diff --git a/src/main/java/org/traccar/protocol/FleetGuideProtocol.java b/src/main/java/org/traccar/protocol/FleetGuideProtocol.java
new file mode 100644
index 000000000..46611c25c
--- /dev/null
+++ b/src/main/java/org/traccar/protocol/FleetGuideProtocol.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2024 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 jakarta.inject.Inject;
+import org.traccar.BaseProtocol;
+import org.traccar.PipelineBuilder;
+import org.traccar.TrackerServer;
+import org.traccar.config.Config;
+
+public class FleetGuideProtocol extends BaseProtocol {
+
+ @Inject
+ public FleetGuideProtocol(Config config) {
+ addServer(new TrackerServer(config, getName(), true) {
+ @Override
+ protected void addProtocolHandlers(PipelineBuilder pipeline, Config config) {
+ pipeline.addLast(new FleetGuideProtocolDecoder(FleetGuideProtocol.this));
+ }
+ });
+ }
+
+}
diff --git a/src/main/java/org/traccar/protocol/FleetGuideProtocolDecoder.java b/src/main/java/org/traccar/protocol/FleetGuideProtocolDecoder.java
new file mode 100644
index 000000000..8f679525b
--- /dev/null
+++ b/src/main/java/org/traccar/protocol/FleetGuideProtocolDecoder.java
@@ -0,0 +1,328 @@
+/*
+ * Copyright 2024 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.buffer.Unpooled;
+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.Checksum;
+import org.traccar.helper.UnitsConverter;
+import org.traccar.model.Position;
+import org.traccar.session.DeviceSession;
+
+import java.net.SocketAddress;
+import java.util.Date;
+import java.util.LinkedList;
+import java.util.List;
+
+public class FleetGuideProtocolDecoder extends BaseProtocolDecoder {
+
+ public FleetGuideProtocolDecoder(Protocol protocol) {
+ super(protocol);
+ }
+
+ public static final int MSG_EMPTY = 0;
+ public static final int MSG_SYNC_REQ = 1;
+ public static final int MSG_SYNC_ACK = 2;
+ public static final int MSG_DATA_R_ACK = 3;
+ public static final int MSG_DATA_N_ACK = 4;
+ public static final int MSG_REP_R_ACK = 5;
+ public static final int MSG_REP_N_ACK = 6;
+
+ @Override
+ protected Object decode(
+ Channel channel, SocketAddress remoteAddress, Object msg) throws Exception {
+
+ ByteBuf buf = (ByteBuf) msg;
+
+ buf.readUnsignedByte(); // signature
+ int options = buf.readUnsignedShortLE();
+ int length = BitUtil.to(options, 11);
+
+ DeviceSession deviceSession;
+ Long deviceId;
+ if (BitUtil.check(options, 11)) {
+ deviceId = buf.readUnsignedIntLE();
+ deviceSession = getDeviceSession(channel, remoteAddress, String.valueOf(deviceId));
+ } else {
+ deviceId = null;
+ deviceSession = getDeviceSession(channel, remoteAddress);
+ }
+ if (deviceSession == null) {
+ return null;
+ }
+
+ int type;
+ Integer index;
+ if (BitUtil.check(options, 12)) {
+ int value = buf.readUnsignedByte();
+ type = BitUtil.to(value, 4);
+ index = BitUtil.from(value, 4);
+ } else {
+ type = 0;
+ index = null;
+ }
+
+ if (type != MSG_DATA_N_ACK && type != MSG_REP_N_ACK) {
+ Integer responseType;
+ if (type == MSG_SYNC_REQ) {
+ responseType = MSG_SYNC_ACK;
+ } else {
+ responseType = null;
+ }
+ sendResponse(channel, remoteAddress, deviceId, responseType, index);
+ }
+
+ if (BitUtil.check(options, 13)) {
+ buf.readUnsignedShortLE(); // acknowledgement
+ }
+
+ ByteBuf data;
+ if (BitUtil.check(options, 14)) {
+ data = decompress(buf.readSlice(length));
+ } else {
+ data = buf.readRetainedSlice(length);
+ }
+
+ List<Position> positions = new LinkedList<>();
+
+ Position position = new Position(getProtocolName());
+ position.setDeviceId(deviceSession.getDeviceId());
+
+ while (data.isReadable()) {
+
+ int recordHeader = data.readUnsignedShortLE();
+ int recordLength = BitUtil.to(recordHeader, 10);
+ int recordType = BitUtil.from(recordHeader, 10);
+ int recordEndIndex = data.readerIndex() + recordLength;
+
+ if (recordType == 0 && position.getDeviceTime() != null) {
+ processPosition(positions, position);
+ position = new Position(getProtocolName());
+ position.setDeviceId(deviceSession.getDeviceId());
+ }
+
+ switch (recordType) {
+ case 0:
+ position.setTime(new Date((data.readUnsignedIntLE() + 1262304000) * 1000)); // since 2010-01-01
+ break;
+ case 1:
+ position.setLatitude(data.readUnsignedIntLE() * 90.0 / 0xFFFFFFFFL);
+ position.setLongitude(data.readUnsignedIntLE() * 180.0 / 0xFFFFFFFFL);
+ int speed = data.readUnsignedShortLE();
+ position.setSpeed(UnitsConverter.knotsFromKph(BitUtil.to(speed, 14) * 0.1));
+ if (BitUtil.check(speed, 14)) {
+ position.setLatitude(-position.getLatitude());
+ }
+ if (BitUtil.check(speed, 15)) {
+ position.setLongitude(-position.getLongitude());
+ }
+ int course = data.readUnsignedShortLE();
+ position.setSpeed(BitUtil.to(course, 9));
+ int motion = BitUtil.between(course, 9, 11);
+ if (motion > 0) {
+ position.set(Position.KEY_MOTION, motion == 1);
+ }
+ position.set(Position.KEY_SATELLITES, BitUtil.from(course, 11));
+ int altitude = data.readUnsignedShortLE();
+ position.setAltitude(BitUtil.to(altitude, 14));
+ if (BitUtil.check(altitude, 14)) {
+ position.setAltitude(-position.getAltitude());
+ }
+ break;
+ case 3:
+ int powerLow = data.readUnsignedByte();
+ int powerFlags = data.readUnsignedByte();
+ int batteryHigh = data.readUnsignedByte();
+ position.set(Position.KEY_POWER, (powerLow + (BitUtil.to(powerFlags, 5) << 8)) * 0.01);
+ position.set(Position.KEY_IGNITION, BitUtil.check(powerFlags, 5));
+ position.set(Position.KEY_BATTERY, (BitUtil.from(powerFlags, 6) + (batteryHigh << 2)) * 0.01);
+ if (recordLength >= 4) {
+ int extraFlags = data.readUnsignedByte();
+ if (BitUtil.check(extraFlags, 0)) {
+ position.set(Position.KEY_ALARM, Position.ALARM_LOW_POWER);
+ }
+ if (BitUtil.check(extraFlags, 1)) {
+ position.set(Position.KEY_ALARM, Position.ALARM_LOW_BATTERY);
+ }
+ }
+ break;
+ case 6:
+ position.set(Position.KEY_INPUT, data.readUnsignedByte());
+ break;
+ case 7:
+ position.set(Position.KEY_OUTPUT, data.readUnsignedByte());
+ break;
+ case 8:
+ int adcMask = data.readUnsignedByte();
+ for (int i = 0; i < 8; i++) {
+ if (BitUtil.check(adcMask, i)) {
+ position.set(Position.PREFIX_ADC + (i + 1), data.readUnsignedShortLE());
+ }
+ }
+ break;
+ case 11:
+ int fuelMask = data.readUnsignedByte();
+ for (int i = 1; i < 8; i++) {
+ if (BitUtil.check(fuelMask, i)) {
+ position.set("fuel" + i, data.readUnsignedShortLE());
+ }
+ }
+ break;
+ case 12:
+ int fuelTempMask = data.readUnsignedByte();
+ for (int i = 1; i < 8; i++) {
+ if (BitUtil.check(fuelTempMask, i)) {
+ position.set("fuelTemp" + i, (int) data.readByte());
+ }
+ }
+ break;
+ case 13:
+ int tempMask = data.readUnsignedByte();
+ for (int i = 0; i < 8; i++) {
+ if (BitUtil.check(tempMask, i)) {
+ position.set(Position.PREFIX_TEMP + (i + 1), data.readShortLE() * 0.01);
+ }
+ }
+ break;
+ case 18:
+ int sensorIndex = data.readUnsignedByte();
+ switch (recordLength - 1) {
+ case 1:
+ position.set("sensor" + sensorIndex, data.readUnsignedByte());
+ break;
+ case 2:
+ position.set("sensor" + sensorIndex, data.readUnsignedShortLE());
+ break;
+ case 4:
+ position.set("sensor" + sensorIndex, data.readUnsignedIntLE());
+ break;
+ default:
+ break;
+ }
+ break;
+ default:
+ break;
+ }
+
+ data.readerIndex(recordEndIndex);
+
+ }
+
+ processPosition(positions, position);
+
+ data.release();
+
+ return positions.isEmpty() ? null : positions;
+ }
+
+ private void processPosition(List<Position> positions, Position position) {
+ if (!position.getAttributes().isEmpty()) {
+ if (position.getFixTime() == null) {
+ position.setTime(new Date());
+ }
+ if (!position.getAttributes().containsKey(Position.KEY_SATELLITES)) {
+ getLastLocation(position, null);
+ }
+ positions.add(position);
+ }
+ }
+
+
+ private void sendResponse(
+ Channel channel, SocketAddress remoteAddress, Long deviceId, Integer type, Integer index) {
+ if (channel != null) {
+
+ ByteBuf response = Unpooled.buffer();
+ response.writeByte(0x53); // signature
+
+ int options = 0;
+ if (deviceId != null) {
+ options |= 1 << 11;
+ }
+ if (type != null) {
+ options |= 1 << 12;
+ }
+ if (index != null) {
+ options |= 1 << 13;
+ }
+ response.writeShortLE(options);
+
+ if (deviceId != null) {
+ response.writeIntLE(deviceId.intValue());
+ }
+ if (type != null) {
+ response.writeByte(type);
+ }
+ if (index != null) {
+ int mask = (1 << (index + 1)) - 1;
+ response.writeShortLE(mask);
+ }
+ response.writeShortLE(Checksum.crc16(
+ Checksum.CRC16_CCITT_FALSE, response.nioBuffer(1, response.writerIndex() - 1)));
+
+ channel.writeAndFlush(new NetworkMessage(response, remoteAddress));
+ }
+ }
+
+ private int readVarSize(ByteBuf buf) {
+ int b;
+ int y = 0;
+ do {
+ b = buf.readUnsignedByte();
+ y = (y << 7) | (b & 0x0000007f);
+ } while ((b & 0x00000080) > 0);
+
+ return y;
+ }
+
+ private ByteBuf decompress(ByteBuf in) {
+
+ ByteBuf out = Unpooled.buffer();
+
+ if (in.readableBytes() < 1) {
+ return out;
+ }
+
+ int marker = in.readUnsignedByte();
+
+ do {
+ int symbol = in.readUnsignedByte();
+ if (symbol == marker) {
+ if (in.getUnsignedByte(in.readerIndex()) == 0) {
+ out.writeByte(marker);
+ in.skipBytes(1);
+ } else {
+ int length = readVarSize(in);
+ int offset = readVarSize(in);
+
+ for (int i = 0; i < length; i++) {
+ out.writeByte(out.getUnsignedByte(out.writerIndex() - offset));
+ }
+ }
+ } else {
+ out.writeByte(symbol);
+ }
+ } while (in.isReadable());
+
+ return out;
+ }
+
+}
diff --git a/src/main/java/org/traccar/protocol/FlespiProtocol.java b/src/main/java/org/traccar/protocol/FlespiProtocol.java
index 374cf77e2..0d8448845 100644
--- a/src/main/java/org/traccar/protocol/FlespiProtocol.java
+++ b/src/main/java/org/traccar/protocol/FlespiProtocol.java
@@ -23,7 +23,7 @@ import org.traccar.PipelineBuilder;
import org.traccar.TrackerServer;
import org.traccar.config.Config;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class FlespiProtocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/FlespiProtocolDecoder.java b/src/main/java/org/traccar/protocol/FlespiProtocolDecoder.java
index 6e6f9c700..ea076afd8 100644
--- a/src/main/java/org/traccar/protocol/FlespiProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/FlespiProtocolDecoder.java
@@ -24,12 +24,12 @@ import org.traccar.Protocol;
import org.traccar.helper.UnitsConverter;
import org.traccar.model.Position;
-import javax.json.Json;
-import javax.json.JsonArray;
-import javax.json.JsonNumber;
-import javax.json.JsonObject;
-import javax.json.JsonString;
-import javax.json.JsonValue;
+import jakarta.json.Json;
+import jakarta.json.JsonArray;
+import jakarta.json.JsonNumber;
+import jakarta.json.JsonObject;
+import jakarta.json.JsonString;
+import jakarta.json.JsonValue;
import java.io.StringReader;
import java.net.SocketAddress;
import java.nio.charset.StandardCharsets;
@@ -125,12 +125,13 @@ public class FlespiProtocolDecoder extends BaseHttpProtocolDecoder {
position.set(Position.KEY_PDOP, ((JsonNumber) value).doubleValue());
return true;
case "din":
+ position.set(Position.KEY_INPUT, ((JsonNumber) value).intValue());
+ return true;
case "dout":
- if (name.equals("din")) {
- position.set(Position.KEY_INPUT, ((JsonNumber) value).intValue());
- } else {
- position.set(Position.KEY_OUTPUT, ((JsonNumber) value).intValue());
- }
+ position.set(Position.KEY_OUTPUT, ((JsonNumber) value).intValue());
+ return true;
+ case "report.reason":
+ position.set(Position.KEY_EVENT, ((JsonNumber) value).intValue());
return true;
case "gps.vehicle.mileage":
position.set(Position.KEY_ODOMETER, ((JsonNumber) value).doubleValue());
@@ -141,6 +142,9 @@ public class FlespiProtocolDecoder extends BaseHttpProtocolDecoder {
case "battery.voltage":
position.set(Position.KEY_BATTERY, ((JsonNumber) value).doubleValue());
return true;
+ case "battery.level":
+ position.set(Position.KEY_BATTERY_LEVEL, ((JsonNumber) value).intValue());
+ return true;
case "fuel.level":
case "can.fuel.level":
position.set(Position.KEY_FUEL_LEVEL, ((JsonNumber) value).doubleValue());
diff --git a/src/main/java/org/traccar/protocol/FlexApiProtocol.java b/src/main/java/org/traccar/protocol/FlexApiProtocol.java
index 088072d2d..b2e3f5d00 100644
--- a/src/main/java/org/traccar/protocol/FlexApiProtocol.java
+++ b/src/main/java/org/traccar/protocol/FlexApiProtocol.java
@@ -24,7 +24,7 @@ import org.traccar.config.Config;
import java.nio.charset.StandardCharsets;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class FlexApiProtocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/FlexApiProtocolDecoder.java b/src/main/java/org/traccar/protocol/FlexApiProtocolDecoder.java
index 2dec44e64..fb76673ca 100644
--- a/src/main/java/org/traccar/protocol/FlexApiProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/FlexApiProtocolDecoder.java
@@ -23,8 +23,8 @@ import org.traccar.model.CellTower;
import org.traccar.model.Network;
import org.traccar.model.Position;
-import javax.json.Json;
-import javax.json.JsonObject;
+import jakarta.json.Json;
+import jakarta.json.JsonObject;
import java.io.StringReader;
import java.net.SocketAddress;
import java.util.Date;
diff --git a/src/main/java/org/traccar/protocol/FlexCommProtocol.java b/src/main/java/org/traccar/protocol/FlexCommProtocol.java
index 5397156cb..293b9b12b 100644
--- a/src/main/java/org/traccar/protocol/FlexCommProtocol.java
+++ b/src/main/java/org/traccar/protocol/FlexCommProtocol.java
@@ -23,7 +23,7 @@ import org.traccar.PipelineBuilder;
import org.traccar.TrackerServer;
import org.traccar.config.Config;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class FlexCommProtocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/FlexibleReportProtocol.java b/src/main/java/org/traccar/protocol/FlexibleReportProtocol.java
index 61e315af9..a16e61458 100644
--- a/src/main/java/org/traccar/protocol/FlexibleReportProtocol.java
+++ b/src/main/java/org/traccar/protocol/FlexibleReportProtocol.java
@@ -20,7 +20,7 @@ import org.traccar.PipelineBuilder;
import org.traccar.TrackerServer;
import org.traccar.config.Config;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class FlexibleReportProtocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/FlextrackProtocol.java b/src/main/java/org/traccar/protocol/FlextrackProtocol.java
index ebac8b4de..b6353de9d 100644
--- a/src/main/java/org/traccar/protocol/FlextrackProtocol.java
+++ b/src/main/java/org/traccar/protocol/FlextrackProtocol.java
@@ -23,7 +23,7 @@ import org.traccar.PipelineBuilder;
import org.traccar.TrackerServer;
import org.traccar.config.Config;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class FlextrackProtocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/FoxProtocol.java b/src/main/java/org/traccar/protocol/FoxProtocol.java
index fa45b3817..edb496f11 100644
--- a/src/main/java/org/traccar/protocol/FoxProtocol.java
+++ b/src/main/java/org/traccar/protocol/FoxProtocol.java
@@ -23,7 +23,7 @@ import org.traccar.PipelineBuilder;
import org.traccar.TrackerServer;
import org.traccar.config.Config;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class FoxProtocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/FreedomProtocol.java b/src/main/java/org/traccar/protocol/FreedomProtocol.java
index dac117c04..87404094a 100644
--- a/src/main/java/org/traccar/protocol/FreedomProtocol.java
+++ b/src/main/java/org/traccar/protocol/FreedomProtocol.java
@@ -23,7 +23,7 @@ import org.traccar.PipelineBuilder;
import org.traccar.TrackerServer;
import org.traccar.config.Config;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class FreedomProtocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/FreematicsProtocol.java b/src/main/java/org/traccar/protocol/FreematicsProtocol.java
index dce4994ab..c4076f330 100644
--- a/src/main/java/org/traccar/protocol/FreematicsProtocol.java
+++ b/src/main/java/org/traccar/protocol/FreematicsProtocol.java
@@ -22,7 +22,7 @@ import org.traccar.PipelineBuilder;
import org.traccar.TrackerServer;
import org.traccar.config.Config;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class FreematicsProtocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/FreematicsProtocolDecoder.java b/src/main/java/org/traccar/protocol/FreematicsProtocolDecoder.java
index 4e5200f37..d0402cc94 100644
--- a/src/main/java/org/traccar/protocol/FreematicsProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/FreematicsProtocolDecoder.java
@@ -153,7 +153,7 @@ public class FreematicsProtocolDecoder extends BaseProtocolDecoder {
position.set(Position.KEY_RSSI, Integer.parseInt(value));
break;
case 0x82:
- position.set(Position.KEY_DEVICE_TEMP, Integer.parseInt(value) * 0.1);
+ position.set(Position.KEY_DEVICE_TEMP, Double.parseDouble(value) * 0.1);
break;
case 0x104:
position.set(Position.KEY_ENGINE_LOAD, Integer.parseInt(value));
@@ -165,7 +165,7 @@ public class FreematicsProtocolDecoder extends BaseProtocolDecoder {
position.set(Position.KEY_RPM, Integer.parseInt(value));
break;
case 0x10d:
- position.set(Position.KEY_OBD_SPEED, UnitsConverter.knotsFromKph(Integer.parseInt(value)));
+ position.set(Position.KEY_OBD_SPEED, Integer.parseInt(value));
break;
case 0x111:
position.set(Position.KEY_THROTTLE, Integer.parseInt(value));
diff --git a/src/main/java/org/traccar/protocol/FutureWayProtocol.java b/src/main/java/org/traccar/protocol/FutureWayProtocol.java
index 715dd3c9c..20586bede 100644
--- a/src/main/java/org/traccar/protocol/FutureWayProtocol.java
+++ b/src/main/java/org/traccar/protocol/FutureWayProtocol.java
@@ -22,7 +22,7 @@ import org.traccar.PipelineBuilder;
import org.traccar.TrackerServer;
import org.traccar.config.Config;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class FutureWayProtocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/G1rusProtocol.java b/src/main/java/org/traccar/protocol/G1rusProtocol.java
index f1823762d..b3904b357 100644
--- a/src/main/java/org/traccar/protocol/G1rusProtocol.java
+++ b/src/main/java/org/traccar/protocol/G1rusProtocol.java
@@ -21,7 +21,7 @@ import org.traccar.PipelineBuilder;
import org.traccar.TrackerServer;
import org.traccar.config.Config;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class G1rusProtocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/GalileoFrameDecoder.java b/src/main/java/org/traccar/protocol/GalileoFrameDecoder.java
index c23d26c83..d90e48287 100644
--- a/src/main/java/org/traccar/protocol/GalileoFrameDecoder.java
+++ b/src/main/java/org/traccar/protocol/GalileoFrameDecoder.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2013 - 2018 Anton Tananaev (anton@traccar.org)
+ * Copyright 2013 - 2023 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.
@@ -22,7 +22,7 @@ import org.traccar.BaseFrameDecoder;
public class GalileoFrameDecoder extends BaseFrameDecoder {
- private static final int MESSAGE_MINIMUM_LENGTH = 5;
+ private static final int MESSAGE_MINIMUM_LENGTH = 6;
@Override
protected Object decode(
@@ -32,9 +32,15 @@ public class GalileoFrameDecoder extends BaseFrameDecoder {
return null;
}
- int length = buf.getUnsignedShortLE(buf.readerIndex() + 1) & 0x7fff;
- if (buf.readableBytes() >= (length + MESSAGE_MINIMUM_LENGTH)) {
- return buf.readRetainedSlice(length + MESSAGE_MINIMUM_LENGTH);
+ int length;
+ if (buf.getByte(buf.readerIndex()) == 0x01 && buf.getUnsignedMedium(buf.readerIndex() + 3) == 0x01001c) {
+ length = 3 + buf.getUnsignedShort(buf.readerIndex() + 1);
+ } else {
+ length = 5 + (buf.getUnsignedShortLE(buf.readerIndex() + 1) & 0x7fff);
+ }
+
+ if (buf.readableBytes() >= length) {
+ return buf.readRetainedSlice(length);
}
return null;
diff --git a/src/main/java/org/traccar/protocol/GalileoProtocol.java b/src/main/java/org/traccar/protocol/GalileoProtocol.java
index 90e95574a..95ce4edde 100644
--- a/src/main/java/org/traccar/protocol/GalileoProtocol.java
+++ b/src/main/java/org/traccar/protocol/GalileoProtocol.java
@@ -21,7 +21,7 @@ import org.traccar.TrackerServer;
import org.traccar.config.Config;
import org.traccar.model.Command;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class GalileoProtocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/GatorProtocol.java b/src/main/java/org/traccar/protocol/GatorProtocol.java
index 7341b69a3..d29ed9ce7 100644
--- a/src/main/java/org/traccar/protocol/GatorProtocol.java
+++ b/src/main/java/org/traccar/protocol/GatorProtocol.java
@@ -20,17 +20,25 @@ import org.traccar.BaseProtocol;
import org.traccar.PipelineBuilder;
import org.traccar.TrackerServer;
import org.traccar.config.Config;
+import org.traccar.model.Command;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class GatorProtocol extends BaseProtocol {
@Inject
public GatorProtocol(Config config) {
+ setSupportedDataCommands(
+ Command.TYPE_POSITION_SINGLE,
+ Command.TYPE_ENGINE_RESUME,
+ Command.TYPE_ENGINE_STOP,
+ Command.TYPE_SET_SPEED_LIMIT,
+ Command.TYPE_SET_ODOMETER);
addServer(new TrackerServer(config, getName(), false) {
@Override
protected void addProtocolHandlers(PipelineBuilder pipeline, Config config) {
pipeline.addLast(new LengthFieldBasedFrameDecoder(1024, 3, 2));
+ pipeline.addLast(new GatorProtocolEncoder(GatorProtocol.this));
pipeline.addLast(new GatorProtocolDecoder(GatorProtocol.this));
}
});
diff --git a/src/main/java/org/traccar/protocol/GatorProtocolDecoder.java b/src/main/java/org/traccar/protocol/GatorProtocolDecoder.java
index 644caee81..a9c620090 100644
--- a/src/main/java/org/traccar/protocol/GatorProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/GatorProtocolDecoder.java
@@ -37,6 +37,11 @@ public class GatorProtocolDecoder extends BaseProtocolDecoder {
}
public static final int MSG_HEARTBEAT = 0x21;
+ public static final int MSG_POSITION_REQUEST = 0x30;
+ public static final int MSG_OVERSPEED_ALARM = 0x3F;
+ public static final int MSG_RESET_MILEAGE = 0x6B;
+ public static final int MSG_RESTORE_OIL_DUCT = 0x38;
+ public static final int MSG_CLOSE_OIL_DUCT = 0x39;
public static final int MSG_POSITION_DATA = 0x80;
public static final int MSG_ROLLCALL_RESPONSE = 0x81;
public static final int MSG_ALARM_DATA = 0x82;
diff --git a/src/main/java/org/traccar/protocol/GatorProtocolEncoder.java b/src/main/java/org/traccar/protocol/GatorProtocolEncoder.java
new file mode 100644
index 000000000..6c6b9a54a
--- /dev/null
+++ b/src/main/java/org/traccar/protocol/GatorProtocolEncoder.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright 2023 Hossain Mohammad Seym (seym45@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 org.traccar.BaseProtocolEncoder;
+import org.traccar.Protocol;
+import org.traccar.helper.Checksum;
+import org.traccar.model.Command;
+
+public class GatorProtocolEncoder extends BaseProtocolEncoder {
+
+ public GatorProtocolEncoder(Protocol protocol) {
+ super(protocol);
+ }
+
+ public ByteBuf encodeId(long deviceId) {
+ ByteBuf buf = Unpooled.buffer();
+
+ String id = getUniqueId(deviceId);
+
+ int firstDigit = Integer.parseInt(id.substring(1, 3)) - 30;
+
+ buf.writeByte(Integer.parseInt(id.substring(3, 5)) | (((firstDigit >> 3) & 1) << 7));
+ buf.writeByte(Integer.parseInt(id.substring(5, 7)) | (((firstDigit >> 2) & 1) << 7));
+ buf.writeByte(Integer.parseInt(id.substring(7, 9)) | (((firstDigit >> 1) & 1) << 7));
+ buf.writeByte(Integer.parseInt(id.substring(9)) | ((firstDigit & 1) << 7));
+
+ return buf;
+ }
+
+ private ByteBuf encodeContent(long deviceId, int type, ByteBuf content) {
+ ByteBuf buf = Unpooled.buffer();
+
+ buf.writeByte(0x24);
+ buf.writeByte(0x24);
+ buf.writeByte(type);
+ buf.writeByte(0x00);
+
+ buf.writeByte(4 + 1 + (content != null ? content.readableBytes() : 0) + 1); // length
+
+ ByteBuf pseudoIPAddress = encodeId(deviceId);
+ buf.writeBytes(pseudoIPAddress);
+
+ if (content != null) {
+ buf.writeBytes(content);
+ }
+
+ int checksum = Checksum.xor(buf.nioBuffer());
+ buf.writeByte(checksum);
+
+ buf.writeByte(0x0D);
+
+ return buf;
+ }
+
+ @Override
+ protected Object encodeCommand(Command command) {
+
+ ByteBuf content = Unpooled.buffer();
+
+ switch (command.getType()) {
+ case Command.TYPE_POSITION_SINGLE:
+ return encodeContent(command.getDeviceId(), GatorProtocolDecoder.MSG_POSITION_REQUEST, null);
+ case Command.TYPE_ENGINE_STOP:
+ return encodeContent(command.getDeviceId(), GatorProtocolDecoder.MSG_CLOSE_OIL_DUCT, null);
+ case Command.TYPE_ENGINE_RESUME:
+ return encodeContent(command.getDeviceId(), GatorProtocolDecoder.MSG_RESTORE_OIL_DUCT, null);
+ case Command.TYPE_SET_SPEED_LIMIT:
+ content.writeByte(command.getInteger(Command.KEY_DATA));
+ return encodeContent(command.getDeviceId(), GatorProtocolDecoder.MSG_RESET_MILEAGE, content);
+ case Command.TYPE_SET_ODOMETER:
+ content.writeShort(command.getInteger(Command.KEY_DATA));
+ return encodeContent(command.getDeviceId(), GatorProtocolDecoder.MSG_OVERSPEED_ALARM, content);
+ default:
+ return null;
+ }
+ }
+}
diff --git a/src/main/java/org/traccar/protocol/GenxProtocol.java b/src/main/java/org/traccar/protocol/GenxProtocol.java
index 97d8633a0..7e5a6a69e 100644
--- a/src/main/java/org/traccar/protocol/GenxProtocol.java
+++ b/src/main/java/org/traccar/protocol/GenxProtocol.java
@@ -22,7 +22,7 @@ import org.traccar.PipelineBuilder;
import org.traccar.TrackerServer;
import org.traccar.config.Config;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class GenxProtocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/Gl100Protocol.java b/src/main/java/org/traccar/protocol/Gl100Protocol.java
index e1748c9a0..fdd79648f 100644
--- a/src/main/java/org/traccar/protocol/Gl100Protocol.java
+++ b/src/main/java/org/traccar/protocol/Gl100Protocol.java
@@ -23,7 +23,7 @@ import org.traccar.PipelineBuilder;
import org.traccar.TrackerServer;
import org.traccar.config.Config;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class Gl100Protocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/Gl200Protocol.java b/src/main/java/org/traccar/protocol/Gl200Protocol.java
index c7b6a8e7c..e3ddbb46e 100644
--- a/src/main/java/org/traccar/protocol/Gl200Protocol.java
+++ b/src/main/java/org/traccar/protocol/Gl200Protocol.java
@@ -22,7 +22,7 @@ import org.traccar.TrackerServer;
import org.traccar.config.Config;
import org.traccar.model.Command;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class Gl200Protocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/Gl200ProtocolDecoder.java b/src/main/java/org/traccar/protocol/Gl200ProtocolDecoder.java
index a9736c9e7..9b4e05c35 100644
--- a/src/main/java/org/traccar/protocol/Gl200ProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/Gl200ProtocolDecoder.java
@@ -22,7 +22,7 @@ import io.netty.buffer.ByteBuf;
import io.netty.channel.Channel;
import org.traccar.Protocol;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
import java.net.SocketAddress;
public class Gl200ProtocolDecoder extends BaseProtocolDecoder {
diff --git a/src/main/java/org/traccar/protocol/Gl200TextProtocolDecoder.java b/src/main/java/org/traccar/protocol/Gl200TextProtocolDecoder.java
index 517499f02..2e5ffa8d6 100644
--- a/src/main/java/org/traccar/protocol/Gl200TextProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/Gl200TextProtocolDecoder.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2012 - 2022 Anton Tananaev (anton@traccar.org)
+ * Copyright 2012 - 2024 Anton Tananaev (anton@traccar.org)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -15,12 +15,15 @@
*/
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.session.DeviceSession;
import org.traccar.NetworkMessage;
import org.traccar.Protocol;
import org.traccar.config.Keys;
import org.traccar.helper.BitUtil;
+import org.traccar.helper.DataConverter;
import org.traccar.helper.Parser;
import org.traccar.helper.PatternBuilder;
import org.traccar.helper.UnitsConverter;
@@ -28,15 +31,14 @@ import org.traccar.model.CellTower;
import org.traccar.model.Network;
import org.traccar.model.Position;
import org.traccar.model.WifiAccessPoint;
-
-import io.netty.buffer.ByteBuf;
-import io.netty.channel.Channel;
+import org.traccar.session.DeviceSession;
import java.net.SocketAddress;
import java.nio.charset.StandardCharsets;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
+import java.util.Date;
import java.util.LinkedList;
import java.util.List;
import java.util.TimeZone;
@@ -47,8 +49,12 @@ public class Gl200TextProtocolDecoder extends BaseProtocolDecoder {
private boolean ignoreFixTime;
+ private final DateFormat dateFormat;
+
public Gl200TextProtocolDecoder(Protocol protocol) {
super(protocol);
+ dateFormat = new SimpleDateFormat("yyyyMMddHHmmss");
+ dateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
}
@Override
@@ -56,21 +62,67 @@ public class Gl200TextProtocolDecoder extends BaseProtocolDecoder {
ignoreFixTime = getConfig().getBoolean(Keys.PROTOCOL_IGNORE_FIX_TIME.withPrefix(getProtocolName()));
}
- private static final Pattern PATTERN_ACK = new PatternBuilder()
- .text("+ACK:GT")
- .expression("...,") // type
- .number("([0-9A-Z]{2}xxxx),") // protocol version
- .number("(d{15}|x{14}),") // imei
- .any().text(",")
- .number("(dddd)(dd)(dd)") // date (yyyymmdd)
- .number("(dd)(dd)(dd),") // time (hhmmss)
- .number("(xxxx)") // counter
- .text("$").optional()
- .compile();
+ private String getDeviceModel(DeviceSession deviceSession, String value) {
+ String model = value.isEmpty() ? getDeviceModel(deviceSession) : value;
+ return model != null ? model.toUpperCase() : "";
+ }
+
+ private Position initPosition(Parser parser, Channel channel, SocketAddress remoteAddress) {
+ if (parser.matches()) {
+ DeviceSession deviceSession = getDeviceSession(channel, remoteAddress, parser.next());
+ if (deviceSession != null) {
+ Position position = new Position(getProtocolName());
+ position.setDeviceId(deviceSession.getDeviceId());
+ return position;
+ }
+ }
+ return null;
+ }
+
+ private void decodeDeviceTime(Position position, Parser parser) {
+ if (parser.hasNext(6)) {
+ if (ignoreFixTime) {
+ position.setTime(parser.nextDateTime());
+ } else {
+ position.setDeviceTime(parser.nextDateTime());
+ }
+ }
+ }
+
+ private Long parseHours(String hoursString) {
+ if (hoursString != null && !hoursString.isEmpty()) {
+ String[] hours = hoursString.split(":");
+ return (Integer.parseInt(hours[0]) * 3600L
+ + (hours.length > 1 ? Integer.parseInt(hours[1]) * 60L : 0)
+ + (hours.length > 2 ? Integer.parseInt(hours[2]) : 0)) * 1000;
+ }
+ return null;
+ }
+
+ private Position decodeAck(Channel channel, SocketAddress remoteAddress, String[] values) throws ParseException {
+ DeviceSession deviceSession = getDeviceSession(channel, remoteAddress, values[2]);
+ if (deviceSession == null) {
+ return null;
+ }
+ if (values[0].equals("+ACK:GTHBD")) {
+ if (channel != null) {
+ channel.writeAndFlush(new NetworkMessage(
+ "+SACK:GTHBD," + values[1] + "," + values[values.length - 1] + "$", remoteAddress));
+ }
+ } else {
+ Position position = new Position(getProtocolName());
+ position.setDeviceId(deviceSession.getDeviceId());
+ getLastLocation(position, dateFormat.parse(values[values.length - 2]));
+ position.setValid(false);
+ position.set(Position.KEY_RESULT, values[0]);
+ return position;
+ }
+ return null;
+ }
private static final Pattern PATTERN_INF = new PatternBuilder()
.text("+").expression("(?:RESP|BUFF):GTINF,")
- .number("[0-9A-Z]{2}xxxx,") // protocol version
+ .expression("(?:.{6}|.{10})?,") // protocol version
.number("(d{15}|x{14}),") // imei
.expression("(?:[0-9A-Z]{17},)?") // vin
.expression("(?:[^,]+)?,") // device name
@@ -109,374 +161,6 @@ public class Gl200TextProtocolDecoder extends BaseProtocolDecoder {
.text("$").optional()
.compile();
- private static final Pattern PATTERN_VER = new PatternBuilder()
- .text("+").expression("(?:RESP|BUFF):GTVER,")
- .number("[0-9A-Z]{2}xxxx,") // protocol version
- .number("(d{15}|x{14}),") // imei
- .expression("[^,]*,") // device name
- .expression("([^,]*),") // device type
- .number("(xxxx),") // firmware version
- .number("(xxxx),") // hardware version
- .number("(dddd)(dd)(dd)") // date (yyyymmdd)
- .number("(dd)(dd)(dd),") // time (hhmmss)
- .number("(xxxx)") // counter
- .text("$").optional()
- .compile();
-
- private static final Pattern PATTERN_LOCATION = new PatternBuilder()
- .number("(d{1,2}.?d?)?,") // hdop
- .number("(d{1,3}.d)?,") // speed
- .number("(d{1,3}.?d?)?,") // course
- .number("(-?d{1,5}.d)?,") // altitude
- .number("(-?d{1,3}.d{6})?,") // longitude
- .number("(-?d{1,2}.d{6})?,") // latitude
- .number("(dddd)(dd)(dd)") // date (yyyymmdd)
- .number("(dd)(dd)(dd)").optional(2) // time (hhmmss)
- .text(",")
- .number("(d+)?,") // mcc
- .number("(d+)?,") // mnc
- .groupBegin()
- .number("(d+),") // lac
- .number("(d+),") // cid
- .or()
- .number("(x+)?,") // lac
- .number("(x+)?,") // cid
- .groupEnd()
- .number("(?:d+|(d+.d))?,") // rssi / odometer
- .compile();
-
- private static final Pattern PATTERN_OBD = new PatternBuilder()
- .text("+RESP:GTOBD,")
- .number("[0-9A-Z]{2}xxxx,") // protocol version
- .number("(d{15}|x{14}),") // imei
- .expression("(?:[0-9A-Z]{17})?,") // vin
- .expression("[^,]{0,20},") // device name
- .expression("[01],") // report type
- .number("x{1,8},") // report mask
- .expression("(?:[0-9A-Z]{17})?,") // vin
- .number("[01],") // obd connect
- .number("(?:d{1,5})?,") // obd voltage
- .number("(?:x{8})?,") // support pids
- .number("(d{1,5})?,") // engine rpm
- .number("(d{1,3})?,") // speed
- .number("(-?d{1,3})?,") // coolant temp
- .number("(d+.?d*|Inf|NaN)?,") // fuel consumption
- .number("(d{1,5})?,") // dtcs cleared distance
- .number("(?:d{1,5})?,")
- .expression("([01])?,") // obd connect
- .number("(d{1,3})?,") // number of dtcs
- .number("(x*),") // dtcs
- .number("(d{1,3})?,") // throttle
- .number("(?:d{1,3})?,") // engine load
- .number("(d{1,3})?,") // fuel level
- .expression("(?:[0-9A],)?") // obd protocol
- .number("(d+),") // odometer
- .expression(PATTERN_LOCATION.pattern())
- .number("(d{1,7}.d)?,") // odometer
- .number("(dddd)(dd)(dd)") // date (yyyymmdd)
- .number("(dd)(dd)(dd)").optional(2) // time (hhmmss)
- .text(",")
- .number("(xxxx)") // count number
- .text("$").optional()
- .compile();
-
- private static final Pattern PATTERN_FRI = new PatternBuilder()
- .text("+").expression("(?:RESP|BUFF):GT...,")
- .number("(?:[0-9A-Z]{2}xxxx)?,") // protocol version
- .number("(d{15}|x{14}),") // imei
- .expression("(?:([0-9A-Z]{17}),)?") // vin
- .expression("[^,]*,") // device name
- .number("(d+)?,") // power
- .number("(d{1,2}),").optional() // report type
- .number("d{1,2},").optional() // count
- .number("d*,").optional() // reserved
- .number("(d+),").optional() // battery
- .expression("((?:")
- .expression(PATTERN_LOCATION.pattern())
- .expression(")+)")
- .groupBegin()
- .number("d{1,2},,")
- .number("(d{1,3}),") // battery
- .number("[01],") // mode
- .number("(?:[01])?,") // motion
- .number("(?:-?d{1,2}.d)?,") // temperature
- .or()
- .number("(d{1,7}.d)?,") // odometer
- .number("(d{5}:dd:dd)?,") // hour meter
- .number("(x+)?,") // adc 1
- .number("(x+)?,") // adc 2
- .number("(d{1,3})?,") // battery
- .number("(?:(xx)(xx)(xx))?,") // device status
- .number("(d+)?,") // rpm
- .number("(?:d+.?d*|Inf|NaN)?,") // fuel consumption
- .number("(d+)?,") // fuel level
- .or()
- .number("(-?d),") // rssi
- .number("(d{1,3}),") // battery
- .or()
- .number("(d{1,7}.d)?,").optional() // odometer
- .number("(d{1,3})?,") // battery
- .groupEnd()
- .any()
- .number("(dddd)(dd)(dd)") // date (yyyymmdd)
- .number("(dd)(dd)(dd)").optional(2) // time (hhmmss)
- .text(",")
- .number("(xxxx)") // count number
- .text("$").optional()
- .compile();
-
- private static final Pattern PATTERN_ERI = new PatternBuilder()
- .text("+").expression("(?:RESP|BUFF):GTERI,")
- .number("(?:[0-9A-Z]{2}xxxx)?,") // protocol version
- .number("(d{15}|x{14}),") // imei
- .expression("[^,]*,") // device name
- .number("(x{8}),") // mask
- .number("(d+)?,") // power
- .number("d{1,2},") // report type
- .number("d{1,2},") // count
- .expression("((?:")
- .expression(PATTERN_LOCATION.pattern())
- .expression(")+)")
- .groupBegin()
- .number("(d{1,7}.d)?,") // odometer
- .number("(d{5}:dd:dd)?,") // hour meter
- .number("(x+)?,") // adc 1
- .number("(x+)?,").optional() // adc 2
- .groupBegin()
- .number("(x+)?,") // adc 3
- .number("(xx),") // inputs
- .number("(xx),") // outputs
- .or()
- .number("(d{1,3})?,") // battery
- .number("(?:(xx)(xx)(xx))?,") // device status
- .groupEnd()
- .expression("(.*)") // additional data
- .or()
- .number("d*,,")
- .number("(d+),") // battery
- .any()
- .groupEnd()
- .number("(dddd)(dd)(dd)") // date (yyyymmdd)
- .number("(dd)(dd)(dd)").optional(2) // time (hhmmss)
- .text(",")
- .number("(xxxx)") // count number
- .text("$").optional()
- .compile();
-
- private static final Pattern PATTERN_IGN = new PatternBuilder()
- .text("+").expression("(?:RESP|BUFF):GTIG[NF],")
- .number("(?:[0-9A-Z]{2}xxxx)?,") // protocol version
- .number("(d{15}|x{14}),") // imei
- .expression("[^,]*,") // device name
- .number("d+,") // ignition off duration
- .expression(PATTERN_LOCATION.pattern())
- .number("(d{5}:dd:dd)?,") // hour meter
- .number("(d{1,7}.d)?,") // odometer
- .number("(dddd)(dd)(dd)") // date (yyyymmdd)
- .number("(dd)(dd)(dd)").optional(2) // time (hhmmss)
- .text(",")
- .number("(xxxx)") // count number
- .text("$").optional()
- .compile();
-
- private static final Pattern PATTERN_LSW = new PatternBuilder()
- .text("+RESP:").expression("GT[LT]SW,")
- .number("(?:[0-9A-Z]{2}xxxx)?,") // protocol version
- .number("(d{15}|x{14}),") // imei
- .expression("[^,]*,") // device name
- .number("[01],") // type
- .number("([01]),") // state
- .expression(PATTERN_LOCATION.pattern())
- .number("(dddd)(dd)(dd)") // date (yyyymmdd)
- .number("(dd)(dd)(dd)").optional(2) // time (hhmmss)
- .text(",")
- .number("(xxxx)") // count number
- .text("$").optional()
- .compile();
-
- private static final Pattern PATTERN_IDA = new PatternBuilder()
- .text("+RESP:GTIDA,")
- .number("(?:[0-9A-Z]{2}xxxx)?,") // protocol version
- .number("(d{15}|x{14}),") // imei
- .expression("[^,]*,,") // device name
- .number("([^,]+),") // rfid
- .expression("[01],") // report type
- .number("1,") // count
- .expression(PATTERN_LOCATION.pattern())
- .number("(d+.d),") // odometer
- .text(",,,,")
- .number("(dddd)(dd)(dd)") // date (yyyymmdd)
- .number("(dd)(dd)(dd)").optional(2) // time (hhmmss)
- .text(",")
- .number("(xxxx)") // count number
- .text("$").optional()
- .compile();
-
- private static final Pattern PATTERN_WIF = new PatternBuilder()
- .text("+RESP:GTWIF,")
- .number("(?:[0-9A-Z]{2}xxxx)?,") // protocol version
- .number("(d{15}|x{14}),") // imei
- .expression("[^,]*,") // device name
- .number("(d+),") // count
- .number("((?:x{12},-?d+,,,,)+),,,,") // wifi
- .number("(d{1,3}),") // battery
- .number("(dddd)(dd)(dd)") // date (yyyymmdd)
- .number("(dd)(dd)(dd)").optional(2) // time (hhmmss)
- .text(",")
- .number("(xxxx)") // count number
- .text("$").optional()
- .compile();
-
- private static final Pattern PATTERN_GSM = new PatternBuilder()
- .text("+RESP:GTGSM,")
- .number("(?:[0-9A-Z]{2}xxxx)?,") // protocol version
- .number("(d{15}|x{14}),") // imei
- .expression("(?:STR|CTN|NMR|RTL),") // fix type
- .expression("(.*)") // cells
- .number("(dddd)(dd)(dd)") // date (yyyymmdd)
- .number("(dd)(dd)(dd)").optional(2) // time (hhmmss)
- .text(",")
- .number("(xxxx)") // count number
- .text("$").optional()
- .compile();
-
- private static final Pattern PATTERN_PNA = new PatternBuilder()
- .text("+RESP:GT").expression("P[NF]A,")
- .number("(?:[0-9A-Z]{2}xxxx)?,") // protocol version
- .number("(d{15}|x{14}),") // imei
- .expression("[^,]*,") // device name
- .number("(dddd)(dd)(dd)") // date (yyyymmdd)
- .number("(dd)(dd)(dd)").optional(2) // time (hhmmss)
- .text(",")
- .number("(xxxx)") // count number
- .text("$").optional()
- .compile();
-
- private static final Pattern PATTERN_DAR = new PatternBuilder()
- .text("+RESP:GTDAR,")
- .number("(?:[0-9A-Z]{2}xxxx)?,") // protocol version
- .number("(d{15}|x{14}),") // imei
- .expression("[^,]*,") // device name
- .number("(d),") // warning type
- .number("(d{1,2}),,,") // fatigue degree
- .expression(PATTERN_LOCATION.pattern())
- .any()
- .number("(dddd)(dd)(dd)") // date (yyyymmdd)
- .number("(dd)(dd)(dd)").optional(2) // time (hhmmss)
- .text(",")
- .number("(xxxx)") // count number
- .text("$").optional()
- .compile();
-
- private static final Pattern PATTERN = new PatternBuilder()
- .text("+").expression("(?:RESP|BUFF):GT...,")
- .number("(?:[0-9A-Z]{2}xxxx)?,") // protocol version
- .number("(d{15}|x{14}),") // imei
- .expression("[^,]*,") // device name
- .number("d*,")
- .number("(x{1,2}),") // report type
- .number("d{1,2},") // count
- .number("d*,").optional() // reserved
- .expression(PATTERN_LOCATION.pattern())
- .groupBegin()
- .number("(?:(d{1,7}.d)|0)?,").optional() // odometer
- .number("(d{1,3})?,") // battery
- .or()
- .number("(d{1,7}.d)?,") // odometer
- .groupEnd()
- .number("(dddd)(dd)(dd)") // date (yyyymmdd)
- .number("(dd)(dd)(dd)") // time (hhmmss)
- .text(",")
- .number("(xxxx)") // count number
- .text("$").optional()
- .compile();
-
- private static final Pattern PATTERN_BASIC = new PatternBuilder()
- .text("+").expression("(?:RESP|BUFF)").text(":")
- .expression("GT...,")
- .number("(?:[0-9A-Z]{2}xxxx)?,").optional() // protocol version
- .number("(d{15}|x{14}),") // imei
- .any()
- .text(",")
- .number("(d{1,2})?,") // hdop
- .number("(d{1,3}.d)?,") // speed
- .number("(d{1,3})?,") // course
- .number("(-?d{1,5}.d)?,") // altitude
- .number("(-?d{1,3}.d{6})?,") // longitude
- .number("(-?d{1,2}.d{6})?,") // latitude
- .number("(dddd)(dd)(dd)") // date (yyyymmdd)
- .number("(dd)(dd)(dd)").optional(2) // time (hhmmss)
- .text(",")
- .number("(d+),") // mcc
- .number("(d+),") // mnc
- .number("(x+),") // lac
- .number("(x+),").optional(4) // cell
- .any()
- .number("(dddd)(dd)(dd)") // date (yyyymmdd)
- .number("(dd)(dd)(dd)").optional(2) // time (hhmmss)
- .text(",")
- .number("(xxxx)") // count number
- .text("$").optional()
- .compile();
-
- private Object decodeAck(Channel channel, SocketAddress remoteAddress, String sentence, String type) {
- Parser parser = new Parser(PATTERN_ACK, sentence);
- if (parser.matches()) {
- String protocolVersion = parser.next();
- DeviceSession deviceSession = getDeviceSession(channel, remoteAddress, parser.next());
- if (deviceSession == null) {
- return null;
- }
- if (type.equals("HBD")) {
- if (channel != null) {
- parser.skip(6);
- channel.writeAndFlush(new NetworkMessage(
- "+SACK:GTHBD," + protocolVersion + "," + parser.next() + "$", remoteAddress));
- }
- } else {
- Position position = new Position(getProtocolName());
- position.setDeviceId(deviceSession.getDeviceId());
- getLastLocation(position, parser.nextDateTime());
- position.setValid(false);
- position.set(Position.KEY_RESULT, "Command " + type + " accepted");
- return position;
- }
- }
- return null;
- }
-
- private Position initPosition(Parser parser, Channel channel, SocketAddress remoteAddress) {
- if (parser.matches()) {
- DeviceSession deviceSession = getDeviceSession(channel, remoteAddress, parser.next());
- if (deviceSession != null) {
- Position position = new Position(getProtocolName());
- position.setDeviceId(deviceSession.getDeviceId());
- return position;
- }
- }
- return null;
- }
-
- private void decodeDeviceTime(Position position, Parser parser) {
- if (parser.hasNext(6)) {
- if (ignoreFixTime) {
- position.setTime(parser.nextDateTime());
- } else {
- position.setDeviceTime(parser.nextDateTime());
- }
- }
- }
-
- private Long parseHours(String hoursString) {
- if (hoursString != null) {
- String[] hours = hoursString.split(":");
- return (long) (Integer.parseInt(hours[0]) * 3600
- + (hours.length > 1 ? Integer.parseInt(hours[1]) * 60 : 0)
- + (hours.length > 2 ? Integer.parseInt(hours[2]) : 0)) * 1000;
- }
- return null;
- }
-
private Object decodeInf(Channel channel, SocketAddress remoteAddress, String sentence) {
Parser parser = new Parser(PATTERN_INF, sentence);
Position position = initPosition(parser, channel, remoteAddress);
@@ -537,6 +221,20 @@ public class Gl200TextProtocolDecoder extends BaseProtocolDecoder {
return position;
}
+ private static final Pattern PATTERN_VER = new PatternBuilder()
+ .text("+").expression("(?:RESP|BUFF):GTVER,")
+ .expression("(?:.{6}|.{10})?,") // protocol version
+ .number("(d{15}|x{14}),") // imei
+ .expression("[^,]*,") // device name
+ .expression("([^,]*),") // device type
+ .number("(xxxx),") // firmware version
+ .number("(xxxx),") // hardware version
+ .number("(dddd)(dd)(dd)") // date (yyyymmdd)
+ .number("(dd)(dd)(dd),") // time (hhmmss)
+ .number("(xxxx)") // counter
+ .text("$").optional()
+ .compile();
+
private Object decodeVer(Channel channel, SocketAddress remoteAddress, String sentence) {
Parser parser = new Parser(PATTERN_VER, sentence);
Position position = initPosition(parser, channel, remoteAddress);
@@ -554,9 +252,35 @@ public class Gl200TextProtocolDecoder extends BaseProtocolDecoder {
}
private void skipLocation(Parser parser) {
- parser.skip(19);
+ parser.skip(20);
}
+ private static final Pattern PATTERN_LOCATION = new PatternBuilder()
+ .number("(d{1,2}.?d?)?,") // hdop
+ .number("(d{1,3}.d)?,") // speed
+ .number("(d{1,3}.?d?)?,") // course
+ .number("(-?d{1,5}.d)?,") // altitude
+ .number("(-?d{1,3}.d{6})?,") // longitude
+ .number("(-?d{1,2}.d{6})?,") // latitude
+ .number("(dddd)(dd)(dd)") // date (yyyymmdd)
+ .number("(dd)(dd)(dd)").optional(2) // time (hhmmss)
+ .groupBegin()
+ .number(",d+") // wifi count
+ .number("((?:,x{12},-d+,,,)+)") // wifi
+ .groupEnd("?")
+ .text(",")
+ .number("(d+)?,") // mcc
+ .number("(d+)?,") // mnc
+ .groupBegin()
+ .number("(d+),") // lac
+ .number("(d+),") // cid
+ .or()
+ .number("(x+)?,") // lac
+ .number("(x+)?,") // cid
+ .groupEnd()
+ .number("(?:d+|(d+.d))?,") // rssi / odometer
+ .compile();
+
private void decodeLocation(Position position, Parser parser) {
Double hdop = parser.nextDouble();
position.setValid(hdop == null || hdop > 0);
@@ -575,22 +299,125 @@ public class Gl200TextProtocolDecoder extends BaseProtocolDecoder {
getLastLocation(position, null);
}
+ Network network = new Network();
+
+ if (parser.hasNext()) {
+ String[] values = parser.next().split(",");
+ for (int i = 0; i < values.length; i += 5) {
+ String mac = values[i + 1].replaceAll("(..)", "$1:");
+ network.addWifiAccessPoint(WifiAccessPoint.from(
+ mac.substring(0, mac.length() - 1), Integer.parseInt(values[i + 2])));
+ }
+ }
+
if (parser.hasNext(6)) {
int mcc = parser.nextInt();
int mnc = parser.nextInt();
if (parser.hasNext(2)) {
- position.setNetwork(new Network(CellTower.from(mcc, mnc, parser.nextInt(), parser.nextInt())));
+ network.addCellTower(CellTower.from(mcc, mnc, parser.nextInt(), parser.nextInt()));
}
if (parser.hasNext(2)) {
- position.setNetwork(new Network(CellTower.from(mcc, mnc, parser.nextHexInt(), parser.nextHexInt())));
+ network.addCellTower(CellTower.from(mcc, mnc, parser.nextHexInt(), parser.nextHexInt()));
}
}
+ if (network.getWifiAccessPoints() != null || network.getCellTowers() != null) {
+ position.setNetwork(network);
+ }
+
if (parser.hasNext()) {
position.set(Position.KEY_ODOMETER, parser.nextDouble() * 1000);
}
}
+ private int decodeLocation(Position position, String model, String[] values, int index) throws ParseException {
+ double hdop = values[index++].isEmpty() ? 0 : Double.parseDouble(values[index - 1]);
+ position.set(Position.KEY_HDOP, hdop);
+
+ position.setSpeed(UnitsConverter.knotsFromKph(
+ values[index++].isEmpty() ? 0 : Double.parseDouble(values[index - 1])));
+ position.setCourse(values[index++].isEmpty() ? 0 : Integer.parseInt(values[index - 1]));
+ position.setAltitude(values[index++].isEmpty() ? 0 : Double.parseDouble(values[index - 1]));
+
+ if (!values[index].isEmpty()) {
+ position.setValid(true);
+ position.setLongitude(values[index++].isEmpty() ? 0 : Double.parseDouble(values[index - 1]));
+ position.setLatitude(values[index++].isEmpty() ? 0 : Double.parseDouble(values[index - 1]));
+ position.setTime(dateFormat.parse(values[index++]));
+ } else {
+ index += 3;
+ getLastLocation(position, null);
+ }
+
+ Network network = new Network();
+
+ if (!values[index].isEmpty()) {
+ network.addCellTower(CellTower.from(
+ Integer.parseInt(values[index++]),
+ Integer.parseInt(values[index++]),
+ Integer.parseInt(values[index++], 16),
+ Long.parseLong(values[index++], 16)));
+ } else {
+ index += 4;
+ }
+
+ if (network.getWifiAccessPoints() != null || network.getCellTowers() != null) {
+ position.setNetwork(network);
+ }
+
+ if (model.startsWith("GL5")) {
+ index += 1; // csq rssi
+ index += 1; // csq ber
+ }
+
+ if (!values[index++].isEmpty()) {
+ int appendMask = Integer.parseInt(values[index - 1]);
+ if (BitUtil.check(appendMask, 0)) {
+ position.set(Position.KEY_SATELLITES, Integer.parseInt(values[index++]));
+ }
+ if (BitUtil.check(appendMask, 1)) {
+ index += 1; // trigger type
+ }
+ }
+
+ return index;
+ }
+
+ private static final Pattern PATTERN_OBD = new PatternBuilder()
+ .text("+RESP:GTOBD,")
+ .expression("(?:.{6}|.{10})?,") // protocol version
+ .number("(d{15}|x{14}),") // imei
+ .expression("(?:[0-9A-Z]{17})?,") // vin
+ .expression("[^,]{0,20},") // device name
+ .expression("[01],") // report type
+ .number("x{1,8},") // report mask
+ .expression("(?:[0-9A-Z]{17})?,") // vin
+ .number("[01],") // obd connect
+ .number("(?:d{1,5})?,") // obd voltage
+ .number("(?:x{8})?,") // support pids
+ .number("(d{1,5})?,") // engine rpm
+ .number("(d{1,3})?,") // speed
+ .number("(-?d{1,3})?,") // coolant temp
+ .number("(d+.?d*|Inf|NaN)?,") // fuel consumption
+ .number("(d{1,5})?,") // dtcs cleared distance
+ .number("(?:d{1,5})?,")
+ .expression("([01])?,") // obd connect
+ .number("(d{1,3})?,") // number of dtcs
+ .number("(x*),") // dtcs
+ .number("(d{1,3})?,") // throttle
+ .number("(?:d{1,3})?,") // engine load
+ .number("(d{1,3})?,") // fuel level
+ .expression("(?:[0-9A],)?") // obd protocol
+ .number("(d+),") // odometer
+ .expression(PATTERN_LOCATION.pattern())
+ .number("(d{1,7}.d)?,") // odometer
+ .number("(dddd)(dd)(dd)") // date (yyyymmdd)
+ .number("(dd)(dd)(dd)").optional(2) // time (hhmmss)
+ .text(",")
+ .number("(xxxx)") // count number
+ .text("$").optional()
+ .compile();
+
private Object decodeObd(Channel channel, SocketAddress remoteAddress, String sentence) {
Parser parser = new Parser(PATTERN_OBD, sentence);
Position position = initPosition(parser, channel, remoteAddress);
@@ -625,104 +452,140 @@ public class Gl200TextProtocolDecoder extends BaseProtocolDecoder {
return position;
}
- private Object decodeCan(Channel channel, SocketAddress remoteAddress, String sentence) throws ParseException {
- Position position = new Position(getProtocolName());
-
+ private Object decodeCan(Channel channel, SocketAddress remoteAddress, String[] v) throws ParseException {
int index = 0;
- String[] values = sentence.split(",");
-
index += 1; // header
index += 1; // protocol version
+ DeviceSession deviceSession = getDeviceSession(channel, remoteAddress, v[index++]);
+ if (deviceSession == null) {
+ return null;
+ }
- DeviceSession deviceSession = getDeviceSession(channel, remoteAddress, values[index++]);
+ Position position = new Position(getProtocolName());
position.setDeviceId(deviceSession.getDeviceId());
- index += 1; // device name
+ String model = getDeviceModel(deviceSession, v[index++]);
index += 1; // report type
- index += 1; // canbus state
- long reportMask = Long.parseLong(values[index++], 16);
+ index += 1; // can bus state
+ long reportMask = Long.parseLong(v[index++], 16);
long reportMaskExt = 0;
if (BitUtil.check(reportMask, 0)) {
- position.set(Position.KEY_VIN, values[index++]);
+ position.set(Position.KEY_VIN, v[index++]);
}
- if (BitUtil.check(reportMask, 1)) {
- position.set(Position.KEY_IGNITION, Integer.parseInt(values[index++]) > 0);
+ if (BitUtil.check(reportMask, 1) && !v[index++].isEmpty()) {
+ position.set(Position.KEY_IGNITION, Integer.parseInt(v[index - 1]) > 0);
}
- if (BitUtil.check(reportMask, 2)) {
- position.set(Position.KEY_OBD_ODOMETER, values[index++]);
+ if (BitUtil.check(reportMask, 2) && !v[index++].isEmpty()) {
+ position.set(Position.KEY_OBD_ODOMETER, Integer.parseInt(v[index - 1].substring(1)));
}
- if (BitUtil.check(reportMask, 3) && !values[index++].isEmpty()) {
- position.set(Position.KEY_FUEL_USED, Double.parseDouble(values[index - 1]));
+ if (BitUtil.check(reportMask, 3) && !v[index++].isEmpty()) {
+ position.set(Position.KEY_FUEL_USED, Double.parseDouble(v[index - 1]));
}
- if (BitUtil.check(reportMask, 5) && !values[index++].isEmpty()) {
- position.set(Position.KEY_RPM, Integer.parseInt(values[index - 1]));
+ if (BitUtil.check(reportMask, 5) && !v[index++].isEmpty()) {
+ position.set(Position.KEY_RPM, Integer.parseInt(v[index - 1]));
}
- if (BitUtil.check(reportMask, 4) && !values[index++].isEmpty()) {
- position.set(Position.KEY_OBD_SPEED, UnitsConverter.knotsFromKph(Integer.parseInt(values[index - 1])));
+ if (BitUtil.check(reportMask, 4) && !v[index++].isEmpty()) {
+ position.set(Position.KEY_OBD_SPEED, Integer.parseInt(v[index - 1]));
}
- if (BitUtil.check(reportMask, 6) && !values[index++].isEmpty()) {
- position.set(Position.KEY_COOLANT_TEMP, Integer.parseInt(values[index - 1]));
+ if (BitUtil.check(reportMask, 6) && !v[index++].isEmpty()) {
+ position.set(Position.KEY_COOLANT_TEMP, Integer.parseInt(v[index - 1]));
}
- if (BitUtil.check(reportMask, 7) && !values[index++].isEmpty()) {
- position.set(Position.KEY_FUEL_CONSUMPTION, Double.parseDouble(values[index - 1].substring(1)));
+ if (BitUtil.check(reportMask, 7) && !v[index++].isEmpty()) {
+ String value = v[index - 1];
+ if (value.startsWith("L/H")) {
+ position.set(Position.KEY_FUEL_CONSUMPTION, Double.parseDouble(value.substring(3)));
+ }
}
- if (BitUtil.check(reportMask, 8) && !values[index++].isEmpty()) {
- position.set(Position.KEY_FUEL_LEVEL, Double.parseDouble(values[index - 1].substring(1)));
+ if (BitUtil.check(reportMask, 8) && !v[index++].isEmpty()) {
+ position.set(Position.KEY_FUEL_LEVEL, Double.parseDouble(v[index - 1].substring(1)));
}
- if (BitUtil.check(reportMask, 9) && !values[index++].isEmpty()) {
- position.set("range", Long.parseLong(values[index - 1]) * 100);
+ if (BitUtil.check(reportMask, 9) && !v[index++].isEmpty()) {
+ position.set("range", Long.parseLong(v[index - 1]) * 100);
}
- if (BitUtil.check(reportMask, 10) && !values[index++].isEmpty()) {
- position.set(Position.KEY_THROTTLE, Integer.parseInt(values[index - 1]));
+ if (BitUtil.check(reportMask, 10) && !v[index++].isEmpty()) {
+ position.set(Position.KEY_THROTTLE, Integer.parseInt(v[index - 1]));
}
- if (BitUtil.check(reportMask, 11) && !values[index++].isEmpty()) {
- position.set(Position.KEY_HOURS, UnitsConverter.msFromHours(Double.parseDouble(values[index - 1])));
+ if (BitUtil.check(reportMask, 11) && !v[index++].isEmpty()) {
+ position.set(Position.KEY_HOURS, UnitsConverter.msFromHours(Double.parseDouble(v[index - 1])));
}
- if (BitUtil.check(reportMask, 12)) {
- position.set("drivingHours", Double.parseDouble(values[index++]));
+ if (BitUtil.check(reportMask, 12) && !v[index++].isEmpty()) {
+ position.set(Position.KEY_DRIVING_TIME, Double.parseDouble(v[index - 1]));
}
- if (BitUtil.check(reportMask, 13)) {
- position.set("idleHours", Double.parseDouble(values[index++]));
+ if (BitUtil.check(reportMask, 13) && !v[index++].isEmpty()) {
+ position.set("idleHours", Double.parseDouble(v[index - 1]));
}
- if (BitUtil.check(reportMask, 14) && !values[index++].isEmpty()) {
- position.set("idleFuelConsumption", Double.parseDouble(values[index - 1]));
+ if (BitUtil.check(reportMask, 14) && !v[index++].isEmpty()) {
+ position.set("idleFuelConsumption", Double.parseDouble(v[index - 1]));
}
- if (BitUtil.check(reportMask, 15) && !values[index++].isEmpty()) {
- position.set(Position.KEY_AXLE_WEIGHT, Integer.parseInt(values[index - 1]));
+ if (BitUtil.check(reportMask, 15) && !v[index++].isEmpty()) {
+ position.set(Position.KEY_AXLE_WEIGHT, Integer.parseInt(v[index - 1]));
}
- if (BitUtil.check(reportMask, 16) && !values[index++].isEmpty()) {
- position.set("tachographInfo", Integer.parseInt(values[index - 1], 16));
+ if (BitUtil.check(reportMask, 16) && !v[index++].isEmpty()) {
+ position.set("tachographInfo", Integer.parseInt(v[index - 1], 16));
}
- if (BitUtil.check(reportMask, 17) && !values[index++].isEmpty()) {
- position.set("indicators", Integer.parseInt(values[index - 1], 16));
+ if (BitUtil.check(reportMask, 17) && !v[index++].isEmpty()) {
+ position.set("indicators", Integer.parseInt(v[index - 1], 16));
}
- if (BitUtil.check(reportMask, 18) && !values[index++].isEmpty()) {
- position.set("lights", Integer.parseInt(values[index - 1], 16));
+ if (BitUtil.check(reportMask, 18) && !v[index++].isEmpty()) {
+ position.set("lights", Integer.parseInt(v[index - 1], 16));
}
- if (BitUtil.check(reportMask, 19) && !values[index++].isEmpty()) {
- position.set("doors", Integer.parseInt(values[index - 1], 16));
+ if (BitUtil.check(reportMask, 19) && !v[index++].isEmpty()) {
+ position.set("doors", Integer.parseInt(v[index - 1], 16));
}
- if (BitUtil.check(reportMask, 20) && !values[index++].isEmpty()) {
- position.set("vehicleOverspeed", Double.parseDouble(values[index - 1]));
+ if (BitUtil.check(reportMask, 20) && !v[index++].isEmpty()) {
+ position.set("vehicleOverspeed", Double.parseDouble(v[index - 1]));
}
- if (BitUtil.check(reportMask, 21) && !values[index++].isEmpty()) {
- position.set("engineOverspeed", Double.parseDouble(values[index - 1]));
+ if (BitUtil.check(reportMask, 21) && !v[index++].isEmpty()) {
+ position.set("engineOverspeed", Double.parseDouble(v[index - 1]));
}
- if (BitUtil.check(reportMask, 29)) {
- reportMaskExt = Long.parseLong(values[index++], 16);
+ if ("GV350M".equals(model)) {
+ if (BitUtil.check(reportMask, 22)) {
+ index += 1; // impulse distance
+ }
+ if (BitUtil.check(reportMask, 23)) {
+ index += 1; // gross vehicle weight
+ }
+ if (BitUtil.check(reportMask, 24)) {
+ index += 1; // catalyst liquid level
+ }
+ } else if ("GV355CEU".equals(model)) {
+ if (BitUtil.check(reportMask, 22)) {
+ index += 1; // impulse distance
+ }
+ if (BitUtil.check(reportMask, 23)) {
+ index += 1; // engine cold starts
+ }
+ if (BitUtil.check(reportMask, 24)) {
+ index += 1; // engine all starts
+ }
+ if (BitUtil.check(reportMask, 25)) {
+ index += 1; // engine starts by ignition
+ }
+ if (BitUtil.check(reportMask, 26)) {
+ index += 1; // total engine cold running time
+ }
+ if (BitUtil.check(reportMask, 27)) {
+ index += 1; // handbrake applies during ride
+ }
+ if (BitUtil.check(reportMask, 28)) {
+ index += 1; // electric report mask
+ }
+ }
+ if (BitUtil.check(reportMask, 29) && !v[index++].isEmpty()) {
+ reportMaskExt = Long.parseLong(v[index - 1], 16);
}
- if (BitUtil.check(reportMaskExt, 0) && !values[index++].isEmpty()) {
- position.set("adBlueLevel", Integer.parseInt(values[index - 1]));
+ if (BitUtil.check(reportMaskExt, 0) && !v[index++].isEmpty()) {
+ position.set("adBlueLevel", Integer.parseInt(v[index - 1]));
}
- if (BitUtil.check(reportMaskExt, 1) && !values[index++].isEmpty()) {
- position.set("axleWeight1", Integer.parseInt(values[index - 1]));
+ if (BitUtil.check(reportMaskExt, 1) && !v[index++].isEmpty()) {
+ position.set("axleWeight1", Integer.parseInt(v[index - 1]));
}
- if (BitUtil.check(reportMaskExt, 2) && !values[index++].isEmpty()) {
- position.set("axleWeight3", Integer.parseInt(values[index - 1]));
+ if (BitUtil.check(reportMaskExt, 2) && !v[index++].isEmpty()) {
+ position.set("axleWeight3", Integer.parseInt(v[index - 1]));
}
- if (BitUtil.check(reportMaskExt, 3) && !values[index++].isEmpty()) {
- position.set("axleWeight4", Integer.parseInt(values[index - 1]));
+ if (BitUtil.check(reportMaskExt, 3) && !v[index++].isEmpty()) {
+ position.set("axleWeight4", Integer.parseInt(v[index - 1]));
}
if (BitUtil.check(reportMaskExt, 4)) {
index += 1; // tachograph overspeed
@@ -733,8 +596,8 @@ public class Gl200TextProtocolDecoder extends BaseProtocolDecoder {
if (BitUtil.check(reportMaskExt, 6)) {
index += 1; // tachograph direction
}
- if (BitUtil.check(reportMaskExt, 7) && !values[index++].isEmpty()) {
- position.set(Position.PREFIX_ADC + 1, Integer.parseInt(values[index - 1]) * 0.001);
+ if (BitUtil.check(reportMaskExt, 7) && !v[index++].isEmpty()) {
+ position.set(Position.PREFIX_ADC + 1, Integer.parseInt(v[index - 1]) * 0.001);
}
if (BitUtil.check(reportMaskExt, 8)) {
index += 1; // pedal breaking factor
@@ -757,20 +620,20 @@ public class Gl200TextProtocolDecoder extends BaseProtocolDecoder {
if (BitUtil.check(reportMaskExt, 14)) {
index += 1; // total brake application
}
- if (BitUtil.check(reportMaskExt, 15) && !values[index++].isEmpty()) {
- position.set("driver1Card", values[index - 1]);
+ if (BitUtil.check(reportMaskExt, 15) && !v[index++].isEmpty()) {
+ position.set("driver1Card", v[index - 1]);
}
- if (BitUtil.check(reportMaskExt, 16) && !values[index++].isEmpty()) {
- position.set("driver2Card", values[index - 1]);
+ if (BitUtil.check(reportMaskExt, 16) && !v[index++].isEmpty()) {
+ position.set("driver2Card", v[index - 1]);
}
- if (BitUtil.check(reportMaskExt, 17) && !values[index++].isEmpty()) {
- position.set("driver1Name", values[index - 1]);
+ if (BitUtil.check(reportMaskExt, 17) && !v[index++].isEmpty()) {
+ position.set("driver1Name", v[index - 1]);
}
- if (BitUtil.check(reportMaskExt, 18) && !values[index++].isEmpty()) {
- position.set("driver2Name", values[index - 1]);
+ if (BitUtil.check(reportMaskExt, 18) && !v[index++].isEmpty()) {
+ position.set("driver2Name", v[index - 1]);
}
- if (BitUtil.check(reportMaskExt, 19) && !values[index++].isEmpty()) {
- position.set("registration", values[index - 1]);
+ if (BitUtil.check(reportMaskExt, 19) && !v[index++].isEmpty()) {
+ position.set("registration", v[index - 1]);
}
if (BitUtil.check(reportMaskExt, 20)) {
index += 1; // expansion information
@@ -788,18 +651,18 @@ public class Gl200TextProtocolDecoder extends BaseProtocolDecoder {
DateFormat dateFormat = new SimpleDateFormat("yyyyMMddHHmmss");
dateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
- if (BitUtil.check(reportMask, 30)) {
- while (values[index].isEmpty()) {
+ if (!"GV355CEU".equals(model) && BitUtil.check(reportMask, 30)) {
+ while (v[index].isEmpty()) {
index += 1;
}
- position.setValid(Integer.parseInt(values[index++]) > 0);
- if (!values[index].isEmpty()) {
- position.setSpeed(UnitsConverter.knotsFromKph(Double.parseDouble(values[index++])));
- position.setCourse(Integer.parseInt(values[index++]));
- position.setAltitude(Double.parseDouble(values[index++]));
- position.setLongitude(Double.parseDouble(values[index++]));
- position.setLatitude(Double.parseDouble(values[index++]));
- position.setTime(dateFormat.parse(values[index++]));
+ position.setValid(Integer.parseInt(v[index++]) > 0);
+ if (!v[index].isEmpty()) {
+ position.setSpeed(UnitsConverter.knotsFromKph(Double.parseDouble(v[index++])));
+ position.setCourse(Integer.parseInt(v[index++]));
+ position.setAltitude(Double.parseDouble(v[index++]));
+ position.setLongitude(Double.parseDouble(v[index++]));
+ position.setLatitude(Double.parseDouble(v[index++]));
+ position.setTime(dateFormat.parse(v[index++]));
} else {
index += 6; // no location
getLastLocation(position, null);
@@ -813,34 +676,79 @@ public class Gl200TextProtocolDecoder extends BaseProtocolDecoder {
index += 1; // reserved
}
+ index = v.length - 2;
if (ignoreFixTime) {
- position.setTime(dateFormat.parse(values[index]));
+ position.setTime(dateFormat.parse(v[index]));
} else {
- position.setDeviceTime(dateFormat.parse(values[index]));
+ position.setDeviceTime(dateFormat.parse(v[index]));
}
return position;
}
- private void decodeStatus(Position position, Parser parser) {
- if (parser.hasNext(3)) {
- int ignition = parser.nextHexInt();
- if (BitUtil.check(ignition, 4)) {
- position.set(Position.KEY_IGNITION, false);
- } else if (BitUtil.check(ignition, 5)) {
- position.set(Position.KEY_IGNITION, true);
- }
- int input = parser.nextHexInt();
- int output = parser.nextHexInt();
- position.set(Position.KEY_INPUT, input);
- position.set(Position.PREFIX_IN + 1, BitUtil.check(input, 1));
- position.set(Position.PREFIX_IN + 2, BitUtil.check(input, 2));
- position.set(Position.KEY_OUTPUT, output);
- position.set(Position.PREFIX_OUT + 1, BitUtil.check(output, 0));
- position.set(Position.PREFIX_OUT + 2, BitUtil.check(output, 1));
- }
+ private void decodeStatus(Position position, long value) {
+ long ignition = BitUtil.between(value, 2 * 8, 3 * 8);
+ if (BitUtil.check(ignition, 4)) {
+ position.set(Position.KEY_IGNITION, false);
+ } else if (BitUtil.check(ignition, 5)) {
+ position.set(Position.KEY_IGNITION, true);
+ }
+ long input = BitUtil.between(value, 8, 2 * 8);
+ long output = BitUtil.to(value, 8);
+ position.set(Position.KEY_INPUT, input);
+ position.set(Position.PREFIX_IN + 1, BitUtil.check(input, 1));
+ position.set(Position.PREFIX_IN + 2, BitUtil.check(input, 2));
+ position.set(Position.KEY_OUTPUT, output);
+ position.set(Position.PREFIX_OUT + 1, BitUtil.check(output, 0));
+ position.set(Position.PREFIX_OUT + 2, BitUtil.check(output, 1));
}
+ private static final Pattern PATTERN_FRI = new PatternBuilder()
+ .text("+").expression("(?:RESP|BUFF):GT...,")
+ .expression("(?:.{6}|.{10})?,") // protocol version
+ .number("(d{15}|x{14}),") // imei
+ .expression("(?:([0-9A-Z]{17}),)?") // vin
+ .expression("[^,]*,") // device name
+ .number("(d+)?,") // power
+ .number("(d{1,2}),").optional() // report type
+ .number("d{1,2},").optional() // count
+ .number("d*,").optional() // reserved
+ .number("(d+),").optional() // battery
+ .expression("((?:")
+ .expression(PATTERN_LOCATION.pattern())
+ .expression(")+)")
+ .groupBegin()
+ .number("d{1,2},")
+ .number("(d{1,5})?,") // battery
+ .number("(d{1,3}),") // battery level
+ .number("[01],") // mode
+ .number("(?:[01])?,") // motion
+ .number("(-?d{1,2}.d)?,") // temperature
+ .or()
+ .number("(d{1,7}.d)?,") // odometer
+ .number("(d{5}:dd:dd)?,") // hour meter
+ .number("(x+)?,") // adc 1
+ .number("(x+)?,") // adc 2
+ .number("(d{1,3})?,") // battery
+ .number("(x{6})?,") // device status
+ .number("(d+)?,") // rpm
+ .number("(?:d+.?d*|Inf|NaN)?,") // fuel consumption
+ .number("(d+)?,") // fuel level
+ .or()
+ .number("(-?d),") // rssi
+ .number("(d{1,3}),") // battery
+ .or()
+ .number("(d{1,7}.d)?,").optional() // odometer
+ .number("(d{1,3})?,") // battery
+ .groupEnd()
+ .any()
+ .number("(dddd)(dd)(dd)") // date (yyyymmdd)
+ .number("(dd)(dd)(dd)").optional(2) // time (hhmmss)
+ .text(",")
+ .number("(xxxx)") // count number
+ .text("$").optional()
+ .compile();
+
private Object decodeFri(Channel channel, SocketAddress remoteAddress, String sentence) {
Parser parser = new Parser(PATTERN_FRI, sentence);
if (!parser.matches()) {
@@ -883,8 +791,10 @@ public class Gl200TextProtocolDecoder extends BaseProtocolDecoder {
}
if (parser.hasNext()) {
- position.set(Position.KEY_BATTERY_LEVEL, parser.nextInt());
+ position.set(Position.KEY_BATTERY, parser.nextInt() * 0.001);
}
+ position.set(Position.KEY_BATTERY_LEVEL, parser.nextInt());
+ position.set(Position.PREFIX_TEMP + 1, parser.nextDouble());
if (parser.hasNext()) {
position.set(Position.KEY_ODOMETER, parser.nextDouble() * 1000);
@@ -894,7 +804,9 @@ public class Gl200TextProtocolDecoder extends BaseProtocolDecoder {
position.set(Position.PREFIX_ADC + 2, parser.next());
position.set(Position.KEY_BATTERY_LEVEL, parser.nextInt());
- decodeStatus(position, parser);
+ if (parser.hasNext()) {
+ decodeStatus(position, parser.nextHexLong());
+ }
position.set(Position.KEY_RPM, parser.nextInt());
position.set(Position.KEY_FUEL_LEVEL, parser.nextInt());
@@ -921,109 +833,112 @@ public class Gl200TextProtocolDecoder extends BaseProtocolDecoder {
return positions;
}
- private Object decodeEri(Channel channel, SocketAddress remoteAddress, String sentence) {
- Parser parser = new Parser(PATTERN_ERI, sentence);
- if (!parser.matches()) {
- return null;
- }
-
- DeviceSession deviceSession = getDeviceSession(channel, remoteAddress, parser.next());
+ private Object decodeEri(Channel channel, SocketAddress remoteAddress, String[] v) throws ParseException {
+ int index = 0;
+ index += 1; // header
+ index += 1; // protocol version
+ DeviceSession deviceSession = getDeviceSession(channel, remoteAddress, v[index++]);
if (deviceSession == null) {
return null;
}
- long mask = parser.nextHexLong();
+ String model = getDeviceModel(deviceSession, v[index++]);
+ long mask = Long.parseLong(v[index++], 16);
+ Double power = v[index++].isEmpty() ? null : Integer.parseInt(v[index - 1]) * 0.001;
+ index += 1; // report type
+ int count = Integer.parseInt(v[index++]);
LinkedList<Position> positions = new LinkedList<>();
-
- Integer power = parser.nextInt();
-
- Parser itemParser = new Parser(PATTERN_LOCATION, parser.next());
- while (itemParser.find()) {
+ for (int i = 0; i < count; i++) {
Position position = new Position(getProtocolName());
position.setDeviceId(deviceSession.getDeviceId());
-
- decodeLocation(position, itemParser);
-
+ index = decodeLocation(position, model, v, index);
positions.add(position);
}
Position position = positions.getLast();
+ position.set(Position.KEY_POWER, power);
- skipLocation(parser);
-
- if (power != null) {
- position.set(Position.KEY_POWER, power * 0.001);
+ if (!model.startsWith("GL5")) {
+ position.set(Position.KEY_ODOMETER, v[index++].isEmpty() ? null : Double.parseDouble(v[index - 1]) * 1000);
+ position.set(Position.KEY_HOURS, parseHours(v[index++]));
+ position.set(Position.PREFIX_ADC + 1, v[index++].isEmpty() ? null : Integer.parseInt(v[index - 1]) * 0.001);
+ }
+ if (model.startsWith("GV") && !model.startsWith("GV6")) {
+ position.set(Position.PREFIX_ADC + 2, v[index++].isEmpty() ? null : Integer.parseInt(v[index - 1]) * 0.001);
}
- if (parser.hasNext(12)) {
-
- position.set(Position.KEY_ODOMETER, parser.nextDouble() * 1000);
- position.set(Position.KEY_HOURS, parseHours(parser.next()));
- position.set(Position.PREFIX_ADC + 1, parser.next());
- position.set(Position.PREFIX_ADC + 2, parser.next());
- position.set(Position.PREFIX_ADC + 3, parser.next());
- if (parser.hasNext(2)) {
- position.set(Position.KEY_INPUT, parser.nextHexInt());
- position.set(Position.KEY_OUTPUT, parser.nextHexInt());
- }
- if (parser.hasNext(4)) {
- position.set(Position.KEY_BATTERY_LEVEL, parser.nextInt());
- decodeStatus(position, parser);
+ position.set(Position.KEY_BATTERY_LEVEL, v[index++].isEmpty() ? null : Integer.parseInt(v[index - 1]));
+ if (model.startsWith("GL5")) {
+ index += 1; // mode selection
+ position.set(Position.KEY_MOTION, v[index++].isEmpty() ? null : Integer.parseInt(v[index - 1]) > 0);
+ } else {
+ if (!v[index++].isEmpty()) {
+ decodeStatus(position, Long.parseLong(v[index - 1]));
}
+ index += 1; // reserved / uart device type
+ }
- int index = 0;
- String[] data = parser.next().split(",");
-
- index += 1; // device type
-
- if (BitUtil.check(mask, 0)) {
- index += 1; // digital fuel sensor data
- }
+ if (BitUtil.check(mask, 0)) {
+ position.set(Position.KEY_FUEL_LEVEL, Integer.parseInt(v[index++], 16));
+ }
- if (BitUtil.check(mask, 1)) {
- int deviceCount = Integer.parseInt(data[index++]);
- for (int i = 1; i <= deviceCount; i++) {
- index += 1; // id
- index += 1; // type
- if (!data[index++].isEmpty()) {
- position.set(Position.PREFIX_TEMP + i, (short) Integer.parseInt(data[index - 1], 16) * 0.0625);
- }
+ if (BitUtil.check(mask, 1)) {
+ int deviceCount = Integer.parseInt(v[index++]);
+ for (int i = 1; i <= deviceCount; i++) {
+ index += 1; // id
+ index += 1; // type
+ if (!v[index++].isEmpty()) {
+ position.set(Position.PREFIX_TEMP + i, (short) Integer.parseInt(v[index - 1], 16) * 0.0625);
}
}
+ }
- if (BitUtil.check(mask, 2)) {
- index += 1; // can data
- }
+ if (BitUtil.check(mask, 2)) {
+ index += 1; // can data
+ }
- if (BitUtil.check(mask, 3) || BitUtil.check(mask, 4)) {
- int deviceCount = Integer.parseInt(data[index++]);
- for (int i = 1; i <= deviceCount; i++) {
- index += 1; // type
- if (BitUtil.check(mask, 3)) {
- position.set(Position.KEY_FUEL_LEVEL, Double.parseDouble(data[index++]));
- }
- if (BitUtil.check(mask, 4)) {
- index += 1; // volume
- }
+ if (BitUtil.check(mask, 3) || BitUtil.check(mask, 4)) {
+ int deviceCount = Integer.parseInt(v[index++]);
+ for (int i = 1; i <= deviceCount; i++) {
+ index += 1; // type
+ if (BitUtil.check(mask, 3)) {
+ position.set(Position.KEY_FUEL_LEVEL, Double.parseDouble(v[index++]));
+ }
+ if (BitUtil.check(mask, 4)) {
+ index += 1; // volume
}
}
-
}
- if (parser.hasNext()) {
- position.set(Position.KEY_BATTERY_LEVEL, parser.nextInt());
- }
-
- decodeDeviceTime(position, parser);
+ Date time = dateFormat.parse(v[v.length - 2]);
if (ignoreFixTime) {
+ position.setTime(time);
positions.clear();
positions.add(position);
+ } else {
+ position.setDeviceTime(time);
}
return positions;
}
+ private static final Pattern PATTERN_IGN = new PatternBuilder()
+ .text("+").expression("(?:RESP|BUFF):GTIG[NF],")
+ .expression("(?:.{6}|.{10})?,") // protocol version
+ .number("(d{15}|x{14}),") // imei
+ .expression("[^,]*,") // device name
+ .number("d+,") // ignition off duration
+ .expression(PATTERN_LOCATION.pattern())
+ .number("(d{5}:dd:dd)?,") // hour meter
+ .number("(d{1,7}.d)?,") // odometer
+ .number("(dddd)(dd)(dd)") // date (yyyymmdd)
+ .number("(dd)(dd)(dd)").optional(2) // time (hhmmss)
+ .text(",")
+ .number("(xxxx)") // count number
+ .text("$").optional()
+ .compile();
+
private Object decodeIgn(Channel channel, SocketAddress remoteAddress, String sentence) {
Parser parser = new Parser(PATTERN_IGN, sentence);
Position position = initPosition(parser, channel, remoteAddress);
@@ -1042,6 +957,21 @@ public class Gl200TextProtocolDecoder extends BaseProtocolDecoder {
return position;
}
+ private static final Pattern PATTERN_LSW = new PatternBuilder()
+ .text("+RESP:").expression("GT[LT]SW,")
+ .expression("(?:.{6}|.{10})?,") // protocol version
+ .number("(d{15}|x{14}),") // imei
+ .expression("[^,]*,") // device name
+ .number("[01],") // type
+ .number("([01]),") // state
+ .expression(PATTERN_LOCATION.pattern())
+ .number("(dddd)(dd)(dd)") // date (yyyymmdd)
+ .number("(dd)(dd)(dd)").optional(2) // time (hhmmss)
+ .text(",")
+ .number("(xxxx)") // count number
+ .text("$").optional()
+ .compile();
+
private Object decodeLsw(Channel channel, SocketAddress remoteAddress, String sentence) {
Parser parser = new Parser(PATTERN_LSW, sentence);
Position position = initPosition(parser, channel, remoteAddress);
@@ -1058,6 +988,24 @@ public class Gl200TextProtocolDecoder extends BaseProtocolDecoder {
return position;
}
+ private static final Pattern PATTERN_IDA = new PatternBuilder()
+ .text("+RESP:GTIDA,")
+ .expression("(?:.{6}|.{10})?,") // protocol version
+ .number("(d{15}|x{14}),") // imei
+ .expression("[^,]*,,") // device name
+ .number("([^,]+),") // rfid
+ .expression("[01],") // report type
+ .number("1,") // count
+ .expression(PATTERN_LOCATION.pattern())
+ .number("(d+.d),") // odometer
+ .text(",,,,")
+ .number("(dddd)(dd)(dd)") // date (yyyymmdd)
+ .number("(dd)(dd)(dd)").optional(2) // time (hhmmss)
+ .text(",")
+ .number("(xxxx)") // count number
+ .text("$").optional()
+ .compile();
+
private Object decodeIda(Channel channel, SocketAddress remoteAddress, String sentence) {
Parser parser = new Parser(PATTERN_IDA, sentence);
Position position = initPosition(parser, channel, remoteAddress);
@@ -1076,6 +1024,21 @@ public class Gl200TextProtocolDecoder extends BaseProtocolDecoder {
return position;
}
+ private static final Pattern PATTERN_WIF = new PatternBuilder()
+ .text("+RESP:GTWIF,")
+ .expression("(?:.{6}|.{10})?,") // protocol version
+ .number("(d{15}|x{14}),") // imei
+ .expression("[^,]*,") // device name
+ .number("(d+),") // count
+ .number("((?:x{12},-?d+,,,,)+),,,,") // wifi
+ .number("(d{1,3}),") // battery
+ .number("(dddd)(dd)(dd)") // date (yyyymmdd)
+ .number("(dd)(dd)(dd)").optional(2) // time (hhmmss)
+ .text(",")
+ .number("(xxxx)") // count number
+ .text("$").optional()
+ .compile();
+
private Object decodeWif(Channel channel, SocketAddress remoteAddress, String sentence) {
Parser parser = new Parser(PATTERN_WIF, sentence);
Position position = initPosition(parser, channel, remoteAddress);
@@ -1102,6 +1065,19 @@ public class Gl200TextProtocolDecoder extends BaseProtocolDecoder {
return position;
}
+ private static final Pattern PATTERN_GSM = new PatternBuilder()
+ .text("+RESP:GTGSM,")
+ .expression("(?:.{6}|.{10})?,") // protocol version
+ .number("(d{15}|x{14}),") // imei
+ .expression("(?:STR|CTN|NMR|RTL),") // fix type
+ .expression("(.*)") // cells
+ .number("(dddd)(dd)(dd)") // date (yyyymmdd)
+ .number("(dd)(dd)(dd)").optional(2) // time (hhmmss)
+ .text(",")
+ .number("(xxxx)") // count number
+ .text("$").optional()
+ .compile();
+
private Object decodeGsm(Channel channel, SocketAddress remoteAddress, String sentence) {
Parser parser = new Parser(PATTERN_GSM, sentence);
Position position = initPosition(parser, channel, remoteAddress);
@@ -1128,6 +1104,18 @@ public class Gl200TextProtocolDecoder extends BaseProtocolDecoder {
return position;
}
+ private static final Pattern PATTERN_PNA = new PatternBuilder()
+ .text("+RESP:GT").expression("P[NF]A,")
+ .expression("(?:.{6}|.{10})?,") // protocol version
+ .number("(d{15}|x{14}),") // imei
+ .expression("[^,]*,") // device name
+ .number("(dddd)(dd)(dd)") // date (yyyymmdd)
+ .number("(dd)(dd)(dd)").optional(2) // time (hhmmss)
+ .text(",")
+ .number("(xxxx)") // count number
+ .text("$").optional()
+ .compile();
+
private Object decodePna(Channel channel, SocketAddress remoteAddress, String sentence) {
Parser parser = new Parser(PATTERN_PNA, sentence);
Position position = initPosition(parser, channel, remoteAddress);
@@ -1142,6 +1130,22 @@ public class Gl200TextProtocolDecoder extends BaseProtocolDecoder {
return position;
}
+ private static final Pattern PATTERN_DAR = new PatternBuilder()
+ .text("+RESP:GTDAR,")
+ .expression("(?:.{6}|.{10})?,") // protocol version
+ .number("(d{15}|x{14}),") // imei
+ .expression("[^,]*,") // device name
+ .number("(d),") // warning type
+ .number("(d{1,2}),,,") // fatigue degree
+ .expression(PATTERN_LOCATION.pattern())
+ .any()
+ .number("(dddd)(dd)(dd)") // date (yyyymmdd)
+ .number("(dd)(dd)(dd)").optional(2) // time (hhmmss)
+ .text(",")
+ .number("(xxxx)") // count number
+ .text("$").optional()
+ .compile();
+
private Object decodeDar(Channel channel, SocketAddress remoteAddress, String sentence) {
Parser parser = new Parser(PATTERN_DAR, sentence);
Position position = initPosition(parser, channel, remoteAddress);
@@ -1165,6 +1169,204 @@ public class Gl200TextProtocolDecoder extends BaseProtocolDecoder {
return position;
}
+ private static final Pattern PATTERN_DTT = new PatternBuilder()
+ .text("+RESP:GTDTT,")
+ .expression("(?:.{6}|.{10})?,") // protocol version
+ .number("(d{15}|x{14}),") // imei
+ .expression("[^,]*,,,") // device name
+ .number("d,") // data type
+ .number("d+,") // data length
+ .number("(x+),") // data
+ .number("(dddd)(dd)(dd)") // date (yyyymmdd)
+ .number("(dd)(dd)(dd)").optional(2) // time (hhmmss)
+ .text(",")
+ .number("(xxxx)") // count number
+ .text("$").optional()
+ .compile();
+
+ private Object decodeDtt(Channel channel, SocketAddress remoteAddress, String sentence) {
+ Parser parser = new Parser(PATTERN_DTT, sentence);
+ Position position = initPosition(parser, channel, remoteAddress);
+ if (position == null) {
+ return null;
+ }
+
+ getLastLocation(position, null);
+
+ String data = Unpooled.wrappedBuffer(DataConverter.parseHex(parser.next()))
+ .toString(StandardCharsets.US_ASCII);
+ if (data.contains("COMB")) {
+ position.set(Position.KEY_FUEL_LEVEL, Double.parseDouble(data.split(",")[2]));
+ } else {
+ position.set(Position.KEY_RESULT, data);
+ }
+
+ decodeDeviceTime(position, parser);
+
+ return position;
+ }
+
+ private static final Pattern PATTERN_BAA = new PatternBuilder()
+ .text("+RESP:GTBAA,")
+ .expression("(?:.{6}|.{10})?,") // protocol version
+ .number("(d{15}|x{14}),") // imei
+ .expression("[^,]*,") // device name
+ .number("x+,") // index
+ .number("d,") // accessory type
+ .number("d,") // accessory model
+ .number("x+,") // alarm type
+ .number("(x{4}),") // append mask
+ .expression("((?:[^,]+,){0,6})") // accessory optionals
+ .expression(PATTERN_LOCATION.pattern())
+ .any()
+ .number("(dddd)(dd)(dd)") // date (yyyymmdd)
+ .number("(dd)(dd)(dd)").optional(2) // time (hhmmss)
+ .text(",")
+ .number("(xxxx)") // count number
+ .text("$").optional()
+ .compile();
+
+ private Object decodeBaa(Channel channel, SocketAddress remoteAddress, String sentence) {
+ Parser parser = new Parser(PATTERN_BAA, sentence);
+ Position position = initPosition(parser, channel, remoteAddress);
+ if (position == null) {
+ return null;
+ }
+
+ int mask = parser.nextHexInt();
+ String[] values = parser.next().split(",");
+ int index = 0;
+ if (BitUtil.check(mask, 0)) {
+ position.set("accessoryName", values[index++]);
+ }
+ if (BitUtil.check(mask, 1)) {
+ position.set("accessoryMac", values[index++]);
+ }
+ if (BitUtil.check(mask, 2)) {
+ position.set("accessoryStatus", Integer.parseInt(values[index++]));
+ }
+ if (BitUtil.check(mask, 3)) {
+ position.set("accessoryVoltage", Integer.parseInt(values[index++]) * 0.001);
+ }
+ if (BitUtil.check(mask, 4)) {
+ position.set("accessoryTemp", Integer.parseInt(values[index++]));
+ }
+ if (BitUtil.check(mask, 5)) {
+ position.set("accessoryHumidity", Integer.parseInt(values[index]));
+ }
+
+ decodeLocation(position, parser);
+
+ decodeDeviceTime(position, parser);
+
+ return position;
+ }
+
+ private static final Pattern PATTERN_BID = new PatternBuilder()
+ .text("+RESP:GTBID,")
+ .expression("(?:.{6}|.{10})?,") // protocol version
+ .number("(d{15}|x{14}),") // imei
+ .expression("[^,]*,") // device name
+ .number("d,") // count
+ .number("d,") // accessory model
+ .number("(x{4}),") // append mask
+ .expression("((?:[^,]+,){0,2})") // accessory optionals
+ .expression(PATTERN_LOCATION.pattern())
+ .any()
+ .number("(dddd)(dd)(dd)") // date (yyyymmdd)
+ .number("(dd)(dd)(dd)").optional(2) // time (hhmmss)
+ .text(",")
+ .number("(xxxx)") // count number
+ .text("$").optional()
+ .compile();
+
+ private Object decodeBid(Channel channel, SocketAddress remoteAddress, String sentence) {
+ Parser parser = new Parser(PATTERN_BID, sentence);
+ Position position = initPosition(parser, channel, remoteAddress);
+ if (position == null) {
+ return null;
+ }
+
+ int mask = parser.nextHexInt();
+ String[] values = parser.next().split(",");
+ int index = 0;
+ if (BitUtil.check(mask, 1)) {
+ position.set("accessoryMac", values[index++]);
+ }
+ if (BitUtil.check(mask, 3)) {
+ position.set("accessoryVoltage", Integer.parseInt(values[index]) * 0.001);
+ }
+
+ decodeLocation(position, parser);
+
+ decodeDeviceTime(position, parser);
+
+ return position;
+ }
+
+ private static final Pattern PATTERN_LSA = new PatternBuilder()
+ .text("+RESP:GTLSA,")
+ .expression("(?:.{6}|.{10})?,") // protocol version
+ .number("(d{15}|x{14}),") // imei
+ .expression("[^,]*,") // device name
+ .number("d,") // event state 1
+ .number("d,") // event state 2
+ .number("d+,") // number
+ .expression(PATTERN_LOCATION.pattern())
+ .number("d+,") // bit error rate
+ .number("(d),") // light level
+ .number("(d+),") // battery level
+ .number("[01],") // mode selection
+ .number("[01]?,") // movement status
+ .number("(-?d+.d)?,") // temperature
+ .number("(dddd)(dd)(dd)") // date (yyyymmdd)
+ .number("(dd)(dd)(dd)").optional(2) // time (hhmmss)
+ .text(",")
+ .number("(xxxx)") // count number
+ .text("$").optional()
+ .compile();
+
+ private Object decodeLsa(Channel channel, SocketAddress remoteAddress, String sentence) {
+ Parser parser = new Parser(PATTERN_LSA, sentence);
+ Position position = initPosition(parser, channel, remoteAddress);
+ if (position == null) {
+ return null;
+ }
+
+ decodeLocation(position, parser);
+
+ position.set("lightLevel", parser.nextInt());
+ position.set(Position.KEY_BATTERY_LEVEL, parser.nextInt());
+ position.set(Position.PREFIX_TEMP + 1, parser.nextDouble());
+
+ decodeDeviceTime(position, parser);
+
+ return position;
+ }
+
+ private static final Pattern PATTERN = new PatternBuilder()
+ .text("+").expression("(?:RESP|BUFF):GT...,")
+ .expression("(?:.{6}|.{10})?,") // protocol version
+ .number("(d{15}|x{14}),") // imei
+ .expression("[^,]*,") // device name
+ .number("d*,")
+ .number("(x{1,2}),") // report type
+ .number("d{1,2},") // count
+ .number("d*,").optional() // reserved
+ .expression(PATTERN_LOCATION.pattern())
+ .groupBegin()
+ .number("(?:(d{1,7}.d)|0)?,").optional() // odometer
+ .number("(d{1,3})?,") // battery
+ .or()
+ .number("(d{1,7}.d)?,") // odometer
+ .groupEnd()
+ .number("(dddd)(dd)(dd)") // date (yyyymmdd)
+ .number("(dd)(dd)(dd)") // time (hhmmss)
+ .text(",")
+ .number("(xxxx)") // count number
+ .text("$").optional()
+ .compile();
+
private Object decodeOther(Channel channel, SocketAddress remoteAddress, String sentence, String type) {
Parser parser = new Parser(PATTERN, sentence);
Position position = initPosition(parser, channel, remoteAddress);
@@ -1215,6 +1417,38 @@ public class Gl200TextProtocolDecoder extends BaseProtocolDecoder {
return position;
}
+ private static final Pattern PATTERN_BASIC = new PatternBuilder()
+ .text("+").expression("(?:RESP|BUFF)").text(":")
+ .expression("GT...,")
+ .expression("[^,]+,").optional() // protocol version
+ .number("(d{15}|x{14}),") // imei
+ .any()
+ .text(",")
+ .number("(d{1,2}),") // hdop
+ .groupBegin()
+ .number("(d{1,3}.d),") // speed
+ .number("(d{1,3}),") // course
+ .number("(-?d{1,5}.d),") // altitude
+ .number("(-?d{1,3}.d{6}),") // longitude
+ .number("(-?d{1,2}.d{6}),") // latitude
+ .number("(dddd)(dd)(dd)") // date (yyyymmdd)
+ .number("(dd)(dd)(dd)") // time (hhmmss)
+ .text(",")
+ .or()
+ .text(",,,,,,")
+ .groupEnd()
+ .number("(d+),") // mcc
+ .number("(d+),") // mnc
+ .number("(x+),") // lac
+ .number("(x+),").optional(4) // cell
+ .any()
+ .number("(dddd)(dd)(dd)") // date (yyyymmdd)
+ .number("(dd)(dd)(dd)").optional(2) // time (hhmmss)
+ .text(",")
+ .number("(xxxx)") // count number
+ .text("$").optional()
+ .compile();
+
private Object decodeBasic(Channel channel, SocketAddress remoteAddress, String sentence, String type) {
Parser parser = new Parser(PATTERN_BASIC, sentence);
Position position = initPosition(parser, channel, remoteAddress);
@@ -1299,17 +1533,19 @@ public class Gl200TextProtocolDecoder extends BaseProtocolDecoder {
protected Object decode(
Channel channel, SocketAddress remoteAddress, Object msg) throws Exception {
- String sentence = ((ByteBuf) msg).toString(StandardCharsets.US_ASCII);
+ String sentence = ((ByteBuf) msg).toString(StandardCharsets.US_ASCII).replaceAll("\\$$", "");
int typeIndex = sentence.indexOf(":GT");
if (typeIndex < 0) {
return null;
}
+ String[] values = sentence.split(",");
+
Object result;
String type = sentence.substring(typeIndex + 3, typeIndex + 6);
if (sentence.startsWith("+ACK")) {
- result = decodeAck(channel, remoteAddress, sentence, type);
+ result = decodeAck(channel, remoteAddress, values);
} else {
switch (type) {
case "INF":
@@ -1319,7 +1555,7 @@ public class Gl200TextProtocolDecoder extends BaseProtocolDecoder {
result = decodeObd(channel, remoteAddress, sentence);
break;
case "CAN":
- result = decodeCan(channel, remoteAddress, sentence);
+ result = decodeCan(channel, remoteAddress, values);
break;
case "CTN":
case "FRI":
@@ -1330,7 +1566,7 @@ public class Gl200TextProtocolDecoder extends BaseProtocolDecoder {
result = decodeFri(channel, remoteAddress, sentence);
break;
case "ERI":
- result = decodeEri(channel, remoteAddress, sentence);
+ result = decodeEri(channel, remoteAddress, values);
break;
case "IGN":
case "IGF":
@@ -1359,6 +1595,18 @@ public class Gl200TextProtocolDecoder extends BaseProtocolDecoder {
case "DAR":
result = decodeDar(channel, remoteAddress, sentence);
break;
+ case "DTT":
+ result = decodeDtt(channel, remoteAddress, sentence);
+ break;
+ case "BAA":
+ result = decodeBaa(channel, remoteAddress, sentence);
+ break;
+ case "BID":
+ result = decodeBid(channel, remoteAddress, sentence);
+ break;
+ case "LSA":
+ result = decodeLsa(channel, remoteAddress, sentence);
+ break;
default:
result = decodeOther(channel, remoteAddress, sentence, type);
break;
@@ -1380,13 +1628,7 @@ public class Gl200TextProtocolDecoder extends BaseProtocolDecoder {
}
if (channel != null && getConfig().getBoolean(Keys.PROTOCOL_ACK.withPrefix(getProtocolName()))) {
- String checksum;
- if (sentence.endsWith("$")) {
- checksum = sentence.substring(sentence.length() - 1 - 4, sentence.length() - 1);
- } else {
- checksum = sentence.substring(sentence.length() - 4);
- }
- channel.writeAndFlush(new NetworkMessage("+SACK:" + checksum + "$", remoteAddress));
+ channel.writeAndFlush(new NetworkMessage("+SACK:" + values[values.length - 1] + "$", remoteAddress));
}
return result;
diff --git a/src/main/java/org/traccar/protocol/GlobalSatProtocol.java b/src/main/java/org/traccar/protocol/GlobalSatProtocol.java
index 16b99f426..13f4f2646 100644
--- a/src/main/java/org/traccar/protocol/GlobalSatProtocol.java
+++ b/src/main/java/org/traccar/protocol/GlobalSatProtocol.java
@@ -24,7 +24,7 @@ import org.traccar.TrackerServer;
import org.traccar.config.Config;
import org.traccar.model.Command;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class GlobalSatProtocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/GlobalstarProtocol.java b/src/main/java/org/traccar/protocol/GlobalstarProtocol.java
index 293f5fda5..1d9b6b6dd 100644
--- a/src/main/java/org/traccar/protocol/GlobalstarProtocol.java
+++ b/src/main/java/org/traccar/protocol/GlobalstarProtocol.java
@@ -23,7 +23,7 @@ import org.traccar.PipelineBuilder;
import org.traccar.TrackerServer;
import org.traccar.config.Config;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class GlobalstarProtocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/GlobalstarProtocolDecoder.java b/src/main/java/org/traccar/protocol/GlobalstarProtocolDecoder.java
index 0ddb95c14..b75e612b8 100644
--- a/src/main/java/org/traccar/protocol/GlobalstarProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/GlobalstarProtocolDecoder.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2019 - 2020 Anton Tananaev (anton@traccar.org)
+ * Copyright 2019 - 2023 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.
@@ -27,6 +27,7 @@ import io.netty.handler.codec.http.HttpHeaderNames;
import io.netty.handler.codec.http.HttpResponseStatus;
import io.netty.handler.codec.http.HttpVersion;
import org.traccar.BaseHttpProtocolDecoder;
+import org.traccar.config.Keys;
import org.traccar.session.DeviceSession;
import org.traccar.NetworkMessage;
import org.traccar.Protocol;
@@ -64,6 +65,12 @@ public class GlobalstarProtocolDecoder extends BaseHttpProtocolDecoder {
private final XPath xPath;
private final XPathExpression messageExpression;
+ private boolean alternative;
+
+ public void setAlternative(boolean alternative) {
+ this.alternative = alternative;
+ }
+
public GlobalstarProtocolDecoder(Protocol protocol) {
super(protocol);
try {
@@ -82,6 +89,11 @@ public class GlobalstarProtocolDecoder extends BaseHttpProtocolDecoder {
}
}
+ @Override
+ protected void init() {
+ this.alternative = getConfig().getBoolean(Keys.PROTOCOL_ALTERNATIVE.withPrefix(getProtocolName()));
+ }
+
private void sendResponse(Channel channel, String messageId) throws TransformerException {
Document document = documentBuilder.newDocument();
@@ -135,32 +147,50 @@ public class GlobalstarProtocolDecoder extends BaseHttpProtocolDecoder {
Position position = new Position(getProtocolName());
position.setDeviceId(deviceSession.getDeviceId());
- position.setValid(true);
position.setTime(new Date(Long.parseLong(xPath.evaluate("unixTime", node)) * 1000));
ByteBuf buf = Unpooled.wrappedBuffer(
DataConverter.parseHex(xPath.evaluate("payload", node).substring(2)));
int flags = buf.readUnsignedByte();
- position.set(Position.PREFIX_IN + 1, !BitUtil.check(flags, 1));
- position.set(Position.PREFIX_IN + 2, !BitUtil.check(flags, 2));
- position.set(Position.KEY_CHARGE, !BitUtil.check(flags, 3));
- if (BitUtil.check(flags, 4)) {
- position.set(Position.KEY_ALARM, Position.ALARM_VIBRATION);
+ int type;
+ if (alternative) {
+ type = BitUtil.to(flags, 1);
+ position.setValid(true);
+ position.set(Position.PREFIX_IN + 1, !BitUtil.check(flags, 1));
+ position.set(Position.PREFIX_IN + 2, !BitUtil.check(flags, 2));
+ position.set(Position.KEY_CHARGE, !BitUtil.check(flags, 3));
+ if (BitUtil.check(flags, 4)) {
+ position.set(Position.KEY_ALARM, Position.ALARM_VIBRATION);
+ }
+ position.setCourse(BitUtil.from(flags, 5) * 45);
+ } else {
+ type = BitUtil.to(flags, 2);
+ if (BitUtil.check(flags, 2)) {
+ position.set("batteryReplace", true);
+ }
+ position.setValid(!BitUtil.check(flags, 3));
}
- position.setCourse(BitUtil.from(flags, 5) * 45);
-
double latitude = buf.readUnsignedMedium() * 90.0 / (1 << 23);
position.setLatitude(latitude > 90 ? latitude - 180 : latitude);
double longitude = buf.readUnsignedMedium() * 180.0 / (1 << 23);
position.setLongitude(longitude > 180 ? longitude - 360 : longitude);
- int speed = buf.readUnsignedByte();
- position.setSpeed(UnitsConverter.knotsFromKph(speed));
-
- position.set("batteryReplace", BitUtil.check(buf.readUnsignedByte(), 7));
+ int speed = 0;
+ if (alternative) {
+ speed = buf.readUnsignedByte();
+ position.setSpeed(UnitsConverter.knotsFromKph(speed));
+ position.set("batteryReplace", BitUtil.check(buf.readUnsignedByte(), 7));
+ } else if (type == 0) {
+ position.set(Position.KEY_INPUT, BitUtil.to(buf.readUnsignedByte(), 4));
+ int other = buf.readUnsignedByte();
+ if (BitUtil.check(other, 4)) {
+ position.set(Position.KEY_ALARM, Position.ALARM_VIBRATION);
+ }
+ position.set(Position.KEY_MOTION, BitUtil.check(other, 6));
+ }
if (speed != 0xff) {
positions.add(position);
diff --git a/src/main/java/org/traccar/protocol/GnxProtocol.java b/src/main/java/org/traccar/protocol/GnxProtocol.java
index 32d642688..cfa496009 100644
--- a/src/main/java/org/traccar/protocol/GnxProtocol.java
+++ b/src/main/java/org/traccar/protocol/GnxProtocol.java
@@ -23,7 +23,7 @@ import org.traccar.PipelineBuilder;
import org.traccar.TrackerServer;
import org.traccar.config.Config;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class GnxProtocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/GoSafeProtocol.java b/src/main/java/org/traccar/protocol/GoSafeProtocol.java
index 607931500..c9c0456a0 100644
--- a/src/main/java/org/traccar/protocol/GoSafeProtocol.java
+++ b/src/main/java/org/traccar/protocol/GoSafeProtocol.java
@@ -23,7 +23,7 @@ import org.traccar.PipelineBuilder;
import org.traccar.TrackerServer;
import org.traccar.config.Config;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class GoSafeProtocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/GoSafeProtocolDecoder.java b/src/main/java/org/traccar/protocol/GoSafeProtocolDecoder.java
index 77649a041..f17ea0e08 100644
--- a/src/main/java/org/traccar/protocol/GoSafeProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/GoSafeProtocolDecoder.java
@@ -93,14 +93,14 @@ public class GoSafeProtocolDecoder extends BaseProtocolDecoder {
position.setSpeed(UnitsConverter.knotsFromKph(Integer.parseInt(values[index - 1])));
}
position.setCourse(Integer.parseInt(values[index++]));
- if (index < values.length) {
- position.setAltitude(Integer.parseInt(values[index++]));
+ if (index < values.length && !values[index++].isEmpty()) {
+ position.setAltitude(Integer.parseInt(values[index - 1]));
}
- if (index < values.length) {
- position.set(Position.KEY_HDOP, Double.parseDouble(values[index++]));
+ if (index < values.length && !values[index++].isEmpty()) {
+ position.set(Position.KEY_HDOP, Double.parseDouble(values[index - 1]));
}
- if (index < values.length) {
- position.set(Position.KEY_VDOP, Double.parseDouble(values[index++]));
+ if (index < values.length && !values[index++].isEmpty()) {
+ position.set(Position.KEY_VDOP, Double.parseDouble(values[index - 1]));
}
break;
case "GSM":
diff --git a/src/main/java/org/traccar/protocol/GotopProtocol.java b/src/main/java/org/traccar/protocol/GotopProtocol.java
index 53fcea0d0..21fbbae99 100644
--- a/src/main/java/org/traccar/protocol/GotopProtocol.java
+++ b/src/main/java/org/traccar/protocol/GotopProtocol.java
@@ -23,7 +23,7 @@ import org.traccar.PipelineBuilder;
import org.traccar.TrackerServer;
import org.traccar.config.Config;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class GotopProtocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/Gps056Protocol.java b/src/main/java/org/traccar/protocol/Gps056Protocol.java
index dbffbfdbb..44fc392be 100644
--- a/src/main/java/org/traccar/protocol/Gps056Protocol.java
+++ b/src/main/java/org/traccar/protocol/Gps056Protocol.java
@@ -20,7 +20,7 @@ import org.traccar.PipelineBuilder;
import org.traccar.TrackerServer;
import org.traccar.config.Config;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class Gps056Protocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/Gps103Protocol.java b/src/main/java/org/traccar/protocol/Gps103Protocol.java
index 2725494c5..8424abfe5 100644
--- a/src/main/java/org/traccar/protocol/Gps103Protocol.java
+++ b/src/main/java/org/traccar/protocol/Gps103Protocol.java
@@ -24,7 +24,7 @@ import org.traccar.TrackerServer;
import org.traccar.config.Config;
import org.traccar.model.Command;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class Gps103Protocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/Gps103ProtocolDecoder.java b/src/main/java/org/traccar/protocol/Gps103ProtocolDecoder.java
index 28efa3c30..d1c35b478 100644
--- a/src/main/java/org/traccar/protocol/Gps103ProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/Gps103ProtocolDecoder.java
@@ -225,7 +225,7 @@ public class Gps103ProtocolDecoder extends BaseProtocolDecoder {
getConfig(), parser.nextHexInt(0), parser.nextHexInt(0))));
}
- if (parser.hasNext(20)) {
+ if (parser.hasNextAny(20)) {
String utcHours = parser.next();
String utcMinutes = parser.next();
diff --git a/src/main/java/org/traccar/protocol/GpsGateProtocol.java b/src/main/java/org/traccar/protocol/GpsGateProtocol.java
index a6a73ae6b..db1e8554a 100644
--- a/src/main/java/org/traccar/protocol/GpsGateProtocol.java
+++ b/src/main/java/org/traccar/protocol/GpsGateProtocol.java
@@ -23,7 +23,7 @@ import org.traccar.PipelineBuilder;
import org.traccar.TrackerServer;
import org.traccar.config.Config;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class GpsGateProtocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/GpsMarkerProtocol.java b/src/main/java/org/traccar/protocol/GpsMarkerProtocol.java
index 12b53342c..f50088b2b 100644
--- a/src/main/java/org/traccar/protocol/GpsMarkerProtocol.java
+++ b/src/main/java/org/traccar/protocol/GpsMarkerProtocol.java
@@ -23,7 +23,7 @@ import org.traccar.PipelineBuilder;
import org.traccar.TrackerServer;
import org.traccar.config.Config;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class GpsMarkerProtocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/GpsmtaProtocol.java b/src/main/java/org/traccar/protocol/GpsmtaProtocol.java
index a474b1e53..e146a816d 100644
--- a/src/main/java/org/traccar/protocol/GpsmtaProtocol.java
+++ b/src/main/java/org/traccar/protocol/GpsmtaProtocol.java
@@ -22,7 +22,7 @@ import org.traccar.PipelineBuilder;
import org.traccar.TrackerServer;
import org.traccar.config.Config;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class GpsmtaProtocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/GranitProtocol.java b/src/main/java/org/traccar/protocol/GranitProtocol.java
index bb66501e2..9ca0fe25e 100644
--- a/src/main/java/org/traccar/protocol/GranitProtocol.java
+++ b/src/main/java/org/traccar/protocol/GranitProtocol.java
@@ -22,7 +22,7 @@ import org.traccar.TrackerServer;
import org.traccar.config.Config;
import org.traccar.model.Command;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class GranitProtocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/Gs100Protocol.java b/src/main/java/org/traccar/protocol/Gs100Protocol.java
index 425ca9330..715d48fc4 100644
--- a/src/main/java/org/traccar/protocol/Gs100Protocol.java
+++ b/src/main/java/org/traccar/protocol/Gs100Protocol.java
@@ -20,7 +20,7 @@ import org.traccar.PipelineBuilder;
import org.traccar.TrackerServer;
import org.traccar.config.Config;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class Gs100Protocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/Gt02Protocol.java b/src/main/java/org/traccar/protocol/Gt02Protocol.java
index fa05761f6..f448feacc 100644
--- a/src/main/java/org/traccar/protocol/Gt02Protocol.java
+++ b/src/main/java/org/traccar/protocol/Gt02Protocol.java
@@ -21,7 +21,7 @@ import org.traccar.PipelineBuilder;
import org.traccar.TrackerServer;
import org.traccar.config.Config;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class Gt02Protocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/Gt06Protocol.java b/src/main/java/org/traccar/protocol/Gt06Protocol.java
index 38278121c..945ec3831 100644
--- a/src/main/java/org/traccar/protocol/Gt06Protocol.java
+++ b/src/main/java/org/traccar/protocol/Gt06Protocol.java
@@ -21,7 +21,7 @@ import org.traccar.TrackerServer;
import org.traccar.config.Config;
import org.traccar.model.Command;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class Gt06Protocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/Gt06ProtocolDecoder.java b/src/main/java/org/traccar/protocol/Gt06ProtocolDecoder.java
index 5b639ddfc..6c0380278 100644
--- a/src/main/java/org/traccar/protocol/Gt06ProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/Gt06ProtocolDecoder.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2012 - 2022 Anton Tananaev (anton@traccar.org)
+ * Copyright 2012 - 2024 Anton Tananaev (anton@traccar.org)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -20,6 +20,7 @@ import io.netty.buffer.ByteBufUtil;
import io.netty.buffer.Unpooled;
import io.netty.channel.Channel;
import org.traccar.BaseProtocolDecoder;
+import org.traccar.helper.BufferUtil;
import org.traccar.session.DeviceSession;
import org.traccar.NetworkMessage;
import org.traccar.Protocol;
@@ -77,11 +78,12 @@ public class Gt06ProtocolDecoder extends BaseProtocolDecoder {
public static final int MSG_HEARTBEAT = 0x23; // GK310
public static final int MSG_ADDRESS_REQUEST = 0x2A; // GK310
public static final int MSG_ADDRESS_RESPONSE = 0x97; // GK310
- public static final int MSG_GPS_LBS_5 = 0x31; // AZ735
- public static final int MSG_GPS_LBS_STATUS_4 = 0x32; // AZ735
- public static final int MSG_WIFI_5 = 0x33; // AZ735
- public static final int MSG_AZ735_GPS = 0x32; // AZ735 / only extended
- public static final int MSG_AZ735_ALARM = 0x33; // AZ735 / only extended
+ public static final int MSG_GPS_LBS_5 = 0x31; // AZ735 & SL4X
+ public static final int MSG_GPS_LBS_STATUS_4 = 0x32; // AZ735 & SL4X
+ public static final int MSG_WIFI_5 = 0x33; // AZ735 & SL4X
+ public static final int MSG_LBS_3 = 0x34; // SL4X
+ public static final int MSG_AZ735_GPS = 0x32; // AZ735 (extended)
+ public static final int MSG_AZ735_ALARM = 0x33; // AZ735 (only extended)
public static final int MSG_X1_GPS = 0x34;
public static final int MSG_X1_PHOTO_INFO = 0x35;
public static final int MSG_X1_PHOTO_DATA = 0x36;
@@ -95,7 +97,7 @@ public class Gt06ProtocolDecoder extends BaseProtocolDecoder {
public static final int MSG_INFO = 0x94;
public static final int MSG_SERIAL = 0x9B;
public static final int MSG_STRING_INFO = 0x21;
- public static final int MSG_GPS_2 = 0xA0; // GK310
+ public static final int MSG_GPS_LBS_7 = 0xA0; // GK310 & JM-VL03
public static final int MSG_LBS_2 = 0xA1; // GK310
public static final int MSG_WIFI_3 = 0xA2; // GK310
public static final int MSG_FENCE_SINGLE = 0xA3; // GK310
@@ -119,6 +121,10 @@ public class Gt06ProtocolDecoder extends BaseProtocolDecoder {
SPACE10X,
STANDARD,
OBD6,
+ WETRUST,
+ JC400,
+ SL4X,
+ SEEWORLD,
}
private Variant variant;
@@ -168,7 +174,7 @@ public class Gt06ProtocolDecoder extends BaseProtocolDecoder {
case MSG_GPS_LBS_STATUS_4:
case MSG_GPS_PHONE:
case MSG_GPS_LBS_EXTEND:
- case MSG_GPS_2:
+ case MSG_GPS_LBS_7:
case MSG_FENCE_SINGLE:
case MSG_FENCE_MULTI:
return true;
@@ -190,7 +196,7 @@ public class Gt06ProtocolDecoder extends BaseProtocolDecoder {
case MSG_GPS_LBS_STATUS_2:
case MSG_GPS_LBS_STATUS_3:
case MSG_GPS_LBS_STATUS_4:
- case MSG_GPS_2:
+ case MSG_GPS_LBS_7:
case MSG_FENCE_SINGLE:
case MSG_FENCE_MULTI:
case MSG_LBS_ALARM:
@@ -267,12 +273,12 @@ public class Gt06ProtocolDecoder extends BaseProtocolDecoder {
}
public static boolean decodeGps(Position position, ByteBuf buf, boolean hasLength, TimeZone timezone) {
- return decodeGps(position, buf, hasLength, true, true, timezone);
+ return decodeGps(position, buf, hasLength, true, true, false, timezone);
}
public static boolean decodeGps(
Position position, ByteBuf buf, boolean hasLength, boolean hasSatellites,
- boolean hasSpeed, TimeZone timezone) {
+ boolean hasSpeed, boolean longSpeed, TimeZone timezone) {
DateBuilder dateBuilder = new DateBuilder(timezone)
.setDate(buf.readUnsignedByte(), buf.readUnsignedByte(), buf.readUnsignedByte())
@@ -291,7 +297,8 @@ public class Gt06ProtocolDecoder extends BaseProtocolDecoder {
double longitude = buf.readUnsignedInt() / 60.0 / 30000.0;
if (hasSpeed) {
- position.setSpeed(UnitsConverter.knotsFromKph(buf.readUnsignedByte()));
+ position.setSpeed(UnitsConverter.knotsFromKph(
+ longSpeed ? buf.readUnsignedShort() : buf.readUnsignedByte()));
}
int flags = buf.readUnsignedShort();
@@ -337,21 +344,21 @@ public class Gt06ProtocolDecoder extends BaseProtocolDecoder {
int mcc = buf.readUnsignedShort();
int mnc;
- if (BitUtil.check(mcc, 15) || type == MSG_GPS_LBS_6) {
+ if (BitUtil.check(mcc, 15) || type == MSG_GPS_LBS_6 || variant == Variant.SL4X) {
mnc = buf.readUnsignedShort();
} else {
mnc = buf.readUnsignedByte();
}
int lac;
- if (type == MSG_LBS_ALARM) {
+ if (type == MSG_LBS_ALARM || type == MSG_GPS_LBS_7) {
lac = buf.readInt();
} else {
lac = buf.readUnsignedShort();
}
long cid;
- if (type == MSG_LBS_ALARM) {
+ if (type == MSG_LBS_ALARM || type == MSG_GPS_LBS_7) {
cid = buf.readLong();
- } else if (type == MSG_GPS_LBS_6) {
+ } else if (type == MSG_GPS_LBS_6 || variant == Variant.SEEWORLD) {
cid = buf.readUnsignedInt();
} else {
cid = buf.readUnsignedMedium();
@@ -434,15 +441,18 @@ public class Gt06ProtocolDecoder extends BaseProtocolDecoder {
return Position.ALARM_REMOVING;
case 0x23:
return Position.ALARM_FALL_DOWN;
+ case 0x28:
+ return Position.ALARM_BRAKING;
case 0x29:
return Position.ALARM_ACCELERATION;
- case 0x30:
- return Position.ALARM_BRAKING;
case 0x2A:
case 0x2B:
+ case 0x2E:
return Position.ALARM_CORNERING;
case 0x2C:
return Position.ALARM_ACCIDENT;
+ case 0x30:
+ return Position.ALARM_JAMMING;
default:
return null;
}
@@ -473,28 +483,21 @@ public class Gt06ProtocolDecoder extends BaseProtocolDecoder {
buf.readUnsignedShort(); // type
deviceSession = getDeviceSession(channel, remoteAddress, imei);
- if (deviceSession != null && !deviceSession.contains(DeviceSession.KEY_TIMEZONE)) {
- deviceSession.set(DeviceSession.KEY_TIMEZONE, getTimeZone(deviceSession.getDeviceId()));
- }
-
- if (dataLength > 10) {
- int extensionBits = buf.readUnsignedShort();
- int hours = (extensionBits >> 4) / 100;
- int minutes = (extensionBits >> 4) % 100;
- int offset = (hours * 60 + minutes) * 60;
- if ((extensionBits & 0x8) != 0) {
- offset = -offset;
- }
- if (deviceSession != null) {
- TimeZone timeZone = deviceSession.get(DeviceSession.KEY_TIMEZONE);
- if (timeZone.getRawOffset() == 0) {
- timeZone.setRawOffset(offset * 1000);
- deviceSession.set(DeviceSession.KEY_TIMEZONE, timeZone);
+ if (deviceSession != null) {
+ TimeZone timeZone = getTimeZone(deviceSession.getDeviceId(), null);
+ if (timeZone == null && dataLength > 10) {
+ int extensionBits = buf.readUnsignedShort();
+ int hours = (extensionBits >> 4) / 100;
+ int minutes = (extensionBits >> 4) % 100;
+ int offset = (hours * 60 + minutes) * 60;
+ if ((extensionBits & 0x8) != 0) {
+ offset = -offset;
}
+ timeZone = TimeZone.getTimeZone("UTC");
+ timeZone.setRawOffset(offset * 1000);
}
- }
+ deviceSession.set(DeviceSession.KEY_TIMEZONE, timeZone);
- if (deviceSession != null) {
sendResponse(channel, false, type, buf.getShort(buf.writerIndex() - 6), null);
}
@@ -545,7 +548,7 @@ public class Gt06ProtocolDecoder extends BaseProtocolDecoder {
return null;
- } else if (type == MSG_X1_GPS) {
+ } else if (type == MSG_X1_GPS && variant != Variant.SL4X) {
buf.readUnsignedInt(); // data and alarm
@@ -678,41 +681,50 @@ public class Gt06ProtocolDecoder extends BaseProtocolDecoder {
return position;
} else if (type == MSG_LBS_MULTIPLE_1 || type == MSG_LBS_MULTIPLE_2 || type == MSG_LBS_MULTIPLE_3
- || type == MSG_LBS_EXTEND || type == MSG_LBS_WIFI || type == MSG_LBS_2
+ || type == MSG_LBS_EXTEND || type == MSG_LBS_WIFI || type == MSG_LBS_2 || type == MSG_LBS_3
|| type == MSG_WIFI_3 || type == MSG_WIFI_5) {
- boolean longFormat = type == MSG_LBS_2 || type == MSG_WIFI_3 || type == MSG_WIFI_5;
-
DateBuilder dateBuilder = new DateBuilder((TimeZone) deviceSession.get(DeviceSession.KEY_TIMEZONE))
.setDate(buf.readUnsignedByte(), buf.readUnsignedByte(), buf.readUnsignedByte())
.setTime(buf.readUnsignedByte(), buf.readUnsignedByte(), buf.readUnsignedByte());
getLastLocation(position, dateBuilder.getDate());
- if (variant == Variant.WANWAY_S20) {
+ if (variant == Variant.WANWAY_S20 || variant == Variant.SL4X) {
buf.readUnsignedByte(); // ta
}
int mcc = buf.readUnsignedShort();
- int mnc = BitUtil.check(mcc, 15) ? buf.readUnsignedShort() : buf.readUnsignedByte();
+ int mnc = BitUtil.check(mcc, 15) || variant == Variant.SL4X
+ ? buf.readUnsignedShort() : buf.readUnsignedByte();
Network network = new Network();
int cellCount = variant == Variant.WANWAY_S20 ? buf.readUnsignedByte() : type == MSG_WIFI_5 ? 6 : 7;
for (int i = 0; i < cellCount; i++) {
- int lac = longFormat ? buf.readInt() : buf.readUnsignedShort();
- int cid = longFormat ? (int) buf.readLong() : buf.readUnsignedMedium();
+ int lac;
+ int cid;
+ if (type == MSG_LBS_2 || type == MSG_WIFI_3) {
+ lac = buf.readInt();
+ cid = (int) buf.readLong();
+ } else if (type == MSG_WIFI_5 || type == MSG_LBS_3) {
+ lac = buf.readUnsignedShort();
+ cid = (int) buf.readUnsignedInt();
+ } else {
+ lac = buf.readUnsignedShort();
+ cid = buf.readUnsignedMedium();
+ }
int rssi = -buf.readUnsignedByte();
if (lac > 0) {
network.addCellTower(CellTower.from(BitUtil.to(mcc, 15), mnc, lac, cid, rssi));
}
}
- if (variant != Variant.WANWAY_S20) {
+ if (variant != Variant.WANWAY_S20 && variant != Variant.SL4X) {
buf.readUnsignedByte(); // ta
}
if (type != MSG_LBS_MULTIPLE_1 && type != MSG_LBS_MULTIPLE_2 && type != MSG_LBS_MULTIPLE_3
- && type != MSG_LBS_2) {
+ && type != MSG_LBS_2 && type != MSG_LBS_3) {
int wifiCount = buf.readUnsignedByte();
for (int i = 0; i < wifiCount; i++) {
String mac = ByteBufUtil.hexDump(buf.readSlice(6)).replaceAll("(..)", "$1:");
@@ -805,7 +817,11 @@ public class Gt06ProtocolDecoder extends BaseProtocolDecoder {
}
if (hasLbs(type) && buf.readableBytes() > 6) {
- decodeLbs(position, buf, type, hasStatus(type) && type != MSG_LBS_ALARM && type != MSG_LBS_STATUS);
+ boolean hasLength = hasStatus(type)
+ && type != MSG_LBS_STATUS
+ && type != MSG_LBS_ALARM
+ && (type != MSG_GPS_LBS_STATUS_1 || variant != Variant.VXT01);
+ decodeLbs(position, buf, type, hasLength);
}
if (hasStatus(type)) {
@@ -821,9 +837,13 @@ public class Gt06ProtocolDecoder extends BaseProtocolDecoder {
buf.readUnsignedByte(); // working mode
position.set(Position.KEY_POWER, buf.readUnsignedShort() / 100.0);
} else {
- position.set(Position.KEY_BATTERY_LEVEL, buf.readUnsignedByte() * 100 / 6);
+ int battery = buf.readUnsignedByte();
+ position.set(Position.KEY_BATTERY_LEVEL, battery <= 6 ? battery * 100 / 6 : battery);
position.set(Position.KEY_RSSI, buf.readUnsignedByte());
- position.set(Position.KEY_ALARM, decodeAlarm(buf.readUnsignedByte()));
+ short alarmExtension = buf.readUnsignedByte();
+ if (variant != Variant.VXT01) {
+ position.set(Position.KEY_ALARM, decodeAlarm(alarmExtension));
+ }
}
}
@@ -833,7 +853,7 @@ public class Gt06ProtocolDecoder extends BaseProtocolDecoder {
String data = buf.readCharSequence(buf.readUnsignedByte(), StandardCharsets.US_ASCII).toString();
buf.readUnsignedByte(); // alarm
buf.readUnsignedByte(); // swiped
- position.set("driverLicense", data.trim());
+ position.set(Position.KEY_CARD, data.trim());
} else if (variant == Variant.BENWAY) {
int mask = buf.readUnsignedShort();
position.set(Position.KEY_IGNITION, BitUtil.check(mask, 8 + 7));
@@ -869,9 +889,30 @@ public class Gt06ProtocolDecoder extends BaseProtocolDecoder {
}
position.set(Position.PREFIX_TEMP + 1, temperature);
position.set(Position.KEY_ODOMETER, buf.readUnsignedInt() * 10);
+ } else if (variant == Variant.WETRUST) {
+ position.set(Position.KEY_ODOMETER, buf.readUnsignedInt());
+ position.set(Position.KEY_CARD, buf.readCharSequence(
+ buf.readUnsignedByte(), StandardCharsets.US_ASCII).toString());
+ position.set(Position.KEY_ALARM, buf.readUnsignedByte() > 0 ? Position.ALARM_GENERAL : null);
+ position.set("cardStatus", buf.readUnsignedByte());
+ position.set(Position.KEY_DRIVING_TIME, buf.readUnsignedShort());
}
}
+ if (type == MSG_GPS_LBS_2 && variant == Variant.SEEWORLD) {
+ position.set(Position.KEY_IGNITION, buf.readUnsignedByte() > 0);
+ buf.readUnsignedByte(); // reporting mode
+ buf.readUnsignedByte(); // supplementary transmission
+ position.set(Position.KEY_ODOMETER, buf.readUnsignedInt());
+ buf.readUnsignedInt(); // travel time
+ int temperature = buf.readUnsignedShort();
+ if (BitUtil.check(temperature, 15)) {
+ temperature = -BitUtil.to(temperature, 15);
+ }
+ position.set(Position.PREFIX_TEMP + 1, temperature * 0.01);
+ position.set("humidity", buf.readUnsignedShort() * 0.01);
+ }
+
if ((type == MSG_GPS_LBS_2 || type == MSG_GPS_LBS_3 || type == MSG_GPS_LBS_4)
&& buf.readableBytes() >= 3 + 6) {
position.set(Position.KEY_IGNITION, buf.readUnsignedByte() > 0);
@@ -898,6 +939,12 @@ public class Gt06ProtocolDecoder extends BaseProtocolDecoder {
}
}
+ if (buf.readableBytes() == 3 + 6 || buf.readableBytes() == 3 + 4 + 6) {
+ position.set(Position.KEY_IGNITION, buf.readUnsignedByte() > 0);
+ buf.readUnsignedByte(); // upload mode
+ position.set(Position.KEY_ARCHIVE, buf.readUnsignedByte() > 0 ? true : null);
+ }
+
if (buf.readableBytes() == 4 + 6) {
position.set(Position.KEY_ODOMETER, buf.readUnsignedInt());
}
@@ -906,24 +953,44 @@ public class Gt06ProtocolDecoder extends BaseProtocolDecoder {
boolean extendedAlarm = dataLength > 7;
if (extendedAlarm) {
- decodeGps(position, buf, false, false, false, deviceSession.get(DeviceSession.KEY_TIMEZONE));
+ if (variant == Variant.JC400) {
+ buf.readUnsignedShort(); // marker
+ buf.readUnsignedByte(); // version
+ }
+ decodeGps(
+ position, buf, false,
+ variant == Variant.JC400, variant == Variant.JC400, variant == Variant.JC400,
+ deviceSession.get(DeviceSession.KEY_TIMEZONE));
} else {
DateBuilder dateBuilder = new DateBuilder((TimeZone) deviceSession.get(DeviceSession.KEY_TIMEZONE))
.setDate(buf.readUnsignedByte(), buf.readUnsignedByte(), buf.readUnsignedByte())
.setTime(buf.readUnsignedByte(), buf.readUnsignedByte(), buf.readUnsignedByte());
getLastLocation(position, dateBuilder.getDate());
}
- short alarmType = buf.readUnsignedByte();
- switch (alarmType) {
+ if (variant == Variant.JC400) {
+ position.set(Position.KEY_POWER, buf.readUnsignedShort() * 0.1);
+ }
+ short event = buf.readUnsignedByte();
+ position.set(Position.KEY_EVENT, event);
+ switch (event) {
case 0x01:
position.set(Position.KEY_ALARM, extendedAlarm ? Position.ALARM_SOS : Position.ALARM_GENERAL);
break;
+ case 0x0E:
+ position.set(Position.KEY_ALARM, Position.ALARM_LOW_POWER);
+ break;
+ case 0x76:
+ position.set(Position.KEY_ALARM, Position.ALARM_TEMPERATURE);
+ break;
case 0x80:
position.set(Position.KEY_ALARM, Position.ALARM_VIBRATION);
break;
case 0x87:
position.set(Position.KEY_ALARM, Position.ALARM_OVERSPEED);
break;
+ case 0x88:
+ position.set(Position.KEY_ALARM, Position.ALARM_POWER_CUT);
+ break;
case 0x90:
position.set(Position.KEY_ALARM, Position.ALARM_ACCELERATION);
break;
@@ -937,7 +1004,6 @@ public class Gt06ProtocolDecoder extends BaseProtocolDecoder {
position.set(Position.KEY_ALARM, Position.ALARM_ACCIDENT);
break;
default:
- position.set(Position.KEY_ALARM, Position.ALARM_GENERAL);
break;
}
@@ -1020,6 +1086,29 @@ public class Gt06ProtocolDecoder extends BaseProtocolDecoder {
position.set(Position.PREFIX_ADC + 1, buf.readUnsignedShort() * 0.01);
return position;
+ } else if (subType == 0x04) {
+
+ CharSequence content = buf.readCharSequence(buf.readableBytes() - 4 - 2, StandardCharsets.US_ASCII);
+ String[] values = content.toString().split(";");
+ for (String value : values) {
+ String[] pair = value.split("=");
+ switch (pair[0]) {
+ case "ALM1":
+ case "ALM2":
+ case "ALM3":
+ position.set("alarm" + pair[0].charAt(3) + "Status", Integer.parseInt(pair[1], 16));
+ case "STA1":
+ position.set("otherStatus", Integer.parseInt(pair[1], 16));
+ break;
+ case "DYD":
+ position.set("engineStatus", Integer.parseInt(pair[1], 16));
+ break;
+ default:
+ break;
+ }
+ }
+ return position;
+
} else if (subType == 0x05) {
if (buf.readableBytes() >= 6 + 1 + 6) {
@@ -1339,19 +1428,13 @@ public class Gt06ProtocolDecoder extends BaseProtocolDecoder {
getLastLocation(position, null);
buf.readUnsignedByte(); // external device type code
- int length = buf.readableBytes() - 9; // line break + checksum + index + checksum + footer
- if (length <= 0) {
- return null;
- } else if (length < 8) {
- position.set(
- Position.PREFIX_TEMP + 1,
- Double.parseDouble(buf.readCharSequence(length - 1, StandardCharsets.US_ASCII).toString()));
+ ByteBuf data = buf.readSlice(buf.readableBytes() - 6); // index + checksum + footer
+ if (BufferUtil.isPrintable(data, data.readableBytes())) {
+ String value = data.readCharSequence(data.readableBytes(), StandardCharsets.US_ASCII).toString();
+ position.set(Position.KEY_RESULT, value.trim());
} else {
- buf.readUnsignedByte(); // card type
- position.set(
- Position.KEY_DRIVER_UNIQUE_ID,
- buf.readCharSequence(length - 1, StandardCharsets.US_ASCII).toString());
+ position.set(Position.KEY_RESULT, ByteBufUtil.hexDump(data));
}
return position;
@@ -1391,6 +1474,18 @@ public class Gt06ProtocolDecoder extends BaseProtocolDecoder {
variant = Variant.SPACE10X;
} else if (header == 0x7878 && type == MSG_STATUS && length == 0x13) {
variant = Variant.OBD6;
+ } else if (header == 0x7878 && type == MSG_GPS_LBS_1 && length == 0x29) {
+ variant = Variant.WETRUST;
+ } else if (header == 0x7878 && type == MSG_ALARM && buf.getUnsignedShort(buf.readerIndex() + 4) == 0xffff) {
+ variant = Variant.JC400;
+ } else if (header == 0x7878 && type == MSG_LBS_3 && length == 0x37) {
+ variant = Variant.SL4X;
+ } else if (header == 0x7878 && type == MSG_GPS_LBS_STATUS_4 && length == 0x27) {
+ variant = Variant.SL4X;
+ } else if (header == 0x7878 && type == MSG_GPS_LBS_2 && length == 0x2f) {
+ variant = Variant.SEEWORLD;
+ } else if (header == 0x7878 && type == MSG_GPS_LBS_STATUS_1 && length == 0x26) {
+ variant = Variant.SEEWORLD;
} else {
variant = Variant.STANDARD;
}
diff --git a/src/main/java/org/traccar/protocol/Gt06ProtocolEncoder.java b/src/main/java/org/traccar/protocol/Gt06ProtocolEncoder.java
index dc5dd446f..fd6bb8451 100644
--- a/src/main/java/org/traccar/protocol/Gt06ProtocolEncoder.java
+++ b/src/main/java/org/traccar/protocol/Gt06ProtocolEncoder.java
@@ -23,7 +23,6 @@ import org.traccar.config.Keys;
import org.traccar.helper.Checksum;
import org.traccar.helper.model.AttributeUtil;
import org.traccar.model.Command;
-import org.traccar.model.Device;
import java.nio.charset.StandardCharsets;
@@ -74,11 +73,11 @@ public class Gt06ProtocolEncoder extends BaseProtocolEncoder {
String password = AttributeUtil.getDevicePassword(
getCacheManager(), command.getDeviceId(), getProtocolName(), "123456");
- Device device = getCacheManager().getObject(Device.class, command.getDeviceId());
+ String model = getDeviceModel(command.getDeviceId());
switch (command.getType()) {
case Command.TYPE_ENGINE_STOP:
- if ("G109".equals(device.getModel())) {
+ if ("G109".equals(model)) {
return encodeContent(command.getDeviceId(), "DYD#");
} else if (alternative) {
return encodeContent(command.getDeviceId(), "DYD," + password + "#");
@@ -86,7 +85,7 @@ public class Gt06ProtocolEncoder extends BaseProtocolEncoder {
return encodeContent(command.getDeviceId(), "Relay,1#");
}
case Command.TYPE_ENGINE_RESUME:
- if ("G109".equals(device.getModel())) {
+ if ("G109".equals(model)) {
return encodeContent(command.getDeviceId(), "HFYD#");
} else if (alternative) {
return encodeContent(command.getDeviceId(), "HFYD," + password + "#");
diff --git a/src/main/java/org/traccar/protocol/Gt30Protocol.java b/src/main/java/org/traccar/protocol/Gt30Protocol.java
index 6b79ba58b..fdfc80502 100644
--- a/src/main/java/org/traccar/protocol/Gt30Protocol.java
+++ b/src/main/java/org/traccar/protocol/Gt30Protocol.java
@@ -23,7 +23,7 @@ import org.traccar.PipelineBuilder;
import org.traccar.TrackerServer;
import org.traccar.config.Config;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class Gt30Protocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/H02Protocol.java b/src/main/java/org/traccar/protocol/H02Protocol.java
index 4e5f8c96a..ba5aeaa26 100644
--- a/src/main/java/org/traccar/protocol/H02Protocol.java
+++ b/src/main/java/org/traccar/protocol/H02Protocol.java
@@ -23,7 +23,7 @@ import org.traccar.config.Config;
import org.traccar.config.Keys;
import org.traccar.model.Command;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class H02Protocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/HaicomProtocol.java b/src/main/java/org/traccar/protocol/HaicomProtocol.java
index f56c605f0..bcc491ada 100644
--- a/src/main/java/org/traccar/protocol/HaicomProtocol.java
+++ b/src/main/java/org/traccar/protocol/HaicomProtocol.java
@@ -23,7 +23,7 @@ import org.traccar.PipelineBuilder;
import org.traccar.TrackerServer;
import org.traccar.config.Config;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class HaicomProtocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/HomtecsProtocol.java b/src/main/java/org/traccar/protocol/HomtecsProtocol.java
index aa2d7d852..c04efb945 100644
--- a/src/main/java/org/traccar/protocol/HomtecsProtocol.java
+++ b/src/main/java/org/traccar/protocol/HomtecsProtocol.java
@@ -22,7 +22,7 @@ import org.traccar.PipelineBuilder;
import org.traccar.TrackerServer;
import org.traccar.config.Config;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class HomtecsProtocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/HoopoProtocol.java b/src/main/java/org/traccar/protocol/HoopoProtocol.java
index 02d8e5a8e..3fc0887d8 100644
--- a/src/main/java/org/traccar/protocol/HoopoProtocol.java
+++ b/src/main/java/org/traccar/protocol/HoopoProtocol.java
@@ -22,7 +22,7 @@ import org.traccar.PipelineBuilder;
import org.traccar.TrackerServer;
import org.traccar.config.Config;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class HoopoProtocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/HoopoProtocolDecoder.java b/src/main/java/org/traccar/protocol/HoopoProtocolDecoder.java
index 708c74f2a..7433e7fce 100644
--- a/src/main/java/org/traccar/protocol/HoopoProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/HoopoProtocolDecoder.java
@@ -21,8 +21,8 @@ import org.traccar.session.DeviceSession;
import org.traccar.Protocol;
import org.traccar.model.Position;
-import javax.json.Json;
-import javax.json.JsonObject;
+import jakarta.json.Json;
+import jakarta.json.JsonObject;
import java.io.StringReader;
import java.net.SocketAddress;
import java.time.OffsetDateTime;
diff --git a/src/main/java/org/traccar/protocol/HuaShengProtocol.java b/src/main/java/org/traccar/protocol/HuaShengProtocol.java
index b1b61e977..7246e97e6 100644
--- a/src/main/java/org/traccar/protocol/HuaShengProtocol.java
+++ b/src/main/java/org/traccar/protocol/HuaShengProtocol.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2016 - 2018 Anton Tananaev (anton@traccar.org)
+ * Copyright 2016 - 2023 Anton Tananaev (anton@traccar.org)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -19,17 +19,25 @@ import org.traccar.BaseProtocol;
import org.traccar.PipelineBuilder;
import org.traccar.TrackerServer;
import org.traccar.config.Config;
+import org.traccar.model.Command;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class HuaShengProtocol extends BaseProtocol {
@Inject
public HuaShengProtocol(Config config) {
+ setSupportedDataCommands(
+ Command.TYPE_POSITION_PERIODIC,
+ Command.TYPE_OUTPUT_CONTROL,
+ Command.TYPE_ALARM_ARM,
+ Command.TYPE_ALARM_DISARM,
+ Command.TYPE_SET_SPEED_LIMIT);
addServer(new TrackerServer(config, getName(), false) {
@Override
protected void addProtocolHandlers(PipelineBuilder pipeline, Config config) {
pipeline.addLast(new HuaShengFrameDecoder());
+ pipeline.addLast(new HuaShengProtocolEncoder(HuaShengProtocol.this));
pipeline.addLast(new HuaShengProtocolDecoder(HuaShengProtocol.this));
}
});
diff --git a/src/main/java/org/traccar/protocol/HuaShengProtocolDecoder.java b/src/main/java/org/traccar/protocol/HuaShengProtocolDecoder.java
index 371691d82..7d634b0f2 100644
--- a/src/main/java/org/traccar/protocol/HuaShengProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/HuaShengProtocolDecoder.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2016 - 2021 Anton Tananaev (anton@traccar.org)
+ * Copyright 2016 - 2023 Anton Tananaev (anton@traccar.org)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -48,6 +48,10 @@ public class HuaShengProtocolDecoder extends BaseProtocolDecoder {
public static final int MSG_UPFAULT_RSP = 0xFF13;
public static final int MSG_HSO_REQ = 0x0002;
public static final int MSG_HSO_RSP = 0x0003;
+ public static final int MSG_SET_REQ = 0xAA04;
+ public static final int MSG_SET_RSP = 0xFF05;
+ public static final int MSG_CTRL_REQ = 0xAA16;
+ public static final int MSG_CTRL_RSP = 0xFF17;
private void sendResponse(Channel channel, int type, int index, ByteBuf content) {
if (channel != null) {
@@ -225,13 +229,14 @@ public class HuaShengProtocolDecoder extends BaseProtocolDecoder {
position.setCourse(buf.readUnsignedShort());
position.setAltitude(buf.readUnsignedShort());
- position.set(Position.KEY_ODOMETER, buf.readUnsignedShort() * 1000);
+ buf.readUnsignedShort(); // odometer speed
Network network = new Network();
while (buf.readableBytes() > 4) {
int subtype = buf.readUnsignedShort();
int length = buf.readUnsignedShort() - 4;
+ int endIndex = buf.readerIndex() + length;
switch (subtype) {
case 0x0001:
int coolantTemperature = buf.readUnsignedByte() - 40;
@@ -249,6 +254,9 @@ public class HuaShengProtocolDecoder extends BaseProtocolDecoder {
position.set(Position.KEY_POWER, buf.readUnsignedShort() * 0.01);
position.set(Position.KEY_FUEL_LEVEL, buf.readUnsignedByte() * 0.4);
buf.readUnsignedInt(); // trip id
+ if (buf.readerIndex() < endIndex) {
+ position.set("adBlueLevel", buf.readUnsignedByte() * 0.4);
+ }
break;
case 0x0005:
position.set(Position.KEY_RSSI, buf.readUnsignedByte());
@@ -256,8 +264,11 @@ public class HuaShengProtocolDecoder extends BaseProtocolDecoder {
buf.readUnsignedInt(); // run time
break;
case 0x0009:
- position.set(
- Position.KEY_VIN, buf.readCharSequence(length, StandardCharsets.US_ASCII).toString());
+ position.set(Position.KEY_VIN, buf.readCharSequence(length, StandardCharsets.US_ASCII).toString());
+ break;
+ case 0x0010:
+ position.set(Position.KEY_ODOMETER, Double.parseDouble(
+ buf.readCharSequence(length, StandardCharsets.US_ASCII).toString()) * 1000);
break;
case 0x0011:
position.set(Position.KEY_HOURS, buf.readUnsignedInt() * 0.05);
@@ -276,7 +287,7 @@ public class HuaShengProtocolDecoder extends BaseProtocolDecoder {
String[] values = cell.split("@");
network.addCellTower(CellTower.from(
Integer.parseInt(values[0]), Integer.parseInt(values[1]),
- Integer.parseInt(values[2], 16), Integer.parseInt(values[3], 16)));
+ Integer.parseInt(values[2], 16), Long.parseLong(values[3], 16)));
}
break;
case 0x0021:
@@ -291,6 +302,7 @@ public class HuaShengProtocolDecoder extends BaseProtocolDecoder {
buf.skipBytes(length);
break;
}
+ buf.readerIndex(endIndex);
}
if (network.getCellTowers() != null || network.getWifiAccessPoints() != null) {
diff --git a/src/main/java/org/traccar/protocol/HuaShengProtocolEncoder.java b/src/main/java/org/traccar/protocol/HuaShengProtocolEncoder.java
new file mode 100644
index 000000000..dc34f7b4e
--- /dev/null
+++ b/src/main/java/org/traccar/protocol/HuaShengProtocolEncoder.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright 2023 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.buffer.Unpooled;
+import org.traccar.BaseProtocolEncoder;
+import org.traccar.Protocol;
+import org.traccar.model.Command;
+
+public class HuaShengProtocolEncoder extends BaseProtocolEncoder {
+
+ public HuaShengProtocolEncoder(Protocol protocol) {
+ super(protocol);
+ }
+
+ private ByteBuf encodeContent(int type, ByteBuf content) {
+
+ ByteBuf buf = Unpooled.buffer();
+ buf.writeByte(0xC0);
+ buf.writeShort(0x0000); // flag and version
+ buf.writeShort(12 + content.readableBytes());
+ buf.writeShort(type);
+ buf.writeShort(0); // checksum
+ buf.writeInt(1); // index
+ buf.writeBytes(content);
+ content.release();
+ buf.writeByte(0xC0);
+
+ return buf;
+ }
+
+ @Override
+ protected Object encodeCommand(Command command) {
+
+ ByteBuf content = Unpooled.buffer(0);
+ switch (command.getType()) {
+ case Command.TYPE_POSITION_PERIODIC:
+ content.writeShort(0x0002);
+ content.writeShort(6); // length
+ content.writeShort(command.getInteger(Command.KEY_FREQUENCY));
+ return encodeContent(HuaShengProtocolDecoder.MSG_SET_REQ, content);
+ case Command.TYPE_OUTPUT_CONTROL:
+ /*
+0x01: Lock the relay1; //relay on
+0x02: Unlock the relay1; //relay off
+0x03: Lock the relay2; //relay2 on
+0x04: Unlock the relay2; //relay2 off
+0x05: Lock the relay3; //relay3 on
+0x06: Unlock the relay3; //realy3 off
+ */
+ content.writeByte(
+ (command.getInteger(Command.KEY_INDEX) - 1) * 2
+ + (2 - command.getInteger(Command.KEY_DATA)));
+ return encodeContent(HuaShengProtocolDecoder.MSG_CTRL_REQ, content);
+ case Command.TYPE_ALARM_ARM:
+ case Command.TYPE_ALARM_DISARM:
+ content.writeShort(0x0001);
+ content.writeShort(5); // length
+ content.writeByte(command.getType().equals(Command.TYPE_ALARM_ARM) ? 1 : 0);
+ return encodeContent(HuaShengProtocolDecoder.MSG_SET_REQ, content);
+ case Command.TYPE_SET_SPEED_LIMIT:
+ content.writeShort(0x0004);
+ content.writeShort(6); // length
+ content.writeShort(command.getInteger(Command.KEY_DATA));
+ return encodeContent(HuaShengProtocolDecoder.MSG_SET_REQ, content);
+ default:
+ return null;
+ }
+ }
+
+}
diff --git a/src/main/java/org/traccar/protocol/HuabaoProtocol.java b/src/main/java/org/traccar/protocol/HuabaoProtocol.java
index c37918b0e..fc12d7d71 100644
--- a/src/main/java/org/traccar/protocol/HuabaoProtocol.java
+++ b/src/main/java/org/traccar/protocol/HuabaoProtocol.java
@@ -21,7 +21,7 @@ import org.traccar.TrackerServer;
import org.traccar.config.Config;
import org.traccar.model.Command;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class HuabaoProtocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/HuabaoProtocolDecoder.java b/src/main/java/org/traccar/protocol/HuabaoProtocolDecoder.java
index d0bbeebb5..0a8540543 100644
--- a/src/main/java/org/traccar/protocol/HuabaoProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/HuabaoProtocolDecoder.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2015 - 2022 Anton Tananaev (anton@traccar.org)
+ * Copyright 2015 - 2023 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.
@@ -131,7 +131,10 @@ public class HuabaoProtocolDecoder extends BaseProtocolDecoder {
if (BitUtil.check(value, 8)) {
return Position.ALARM_POWER_OFF;
}
- if (BitUtil.check(value, 17)) {
+ if (BitUtil.check(value, 15)) {
+ return Position.ALARM_VIBRATION;
+ }
+ if (BitUtil.check(value, 16) || BitUtil.check(value, 17)) {
return Position.ALARM_TAMPERING;
}
if (BitUtil.check(value, 20)) {
@@ -140,7 +143,7 @@ public class HuabaoProtocolDecoder extends BaseProtocolDecoder {
if (BitUtil.check(value, 28)) {
return Position.ALARM_MOVEMENT;
}
- if (BitUtil.check(value, 29)) {
+ if (BitUtil.check(value, 29) || BitUtil.check(value, 30)) {
return Position.ALARM_ACCIDENT;
}
return null;
@@ -169,7 +172,7 @@ public class HuabaoProtocolDecoder extends BaseProtocolDecoder {
} else {
long imei = id.getUnsignedShort(0);
imei = (imei << 32) + id.getUnsignedInt(2);
- return String.valueOf(imei);
+ return String.valueOf(imei) + Checksum.luhn(imei);
}
}
@@ -294,6 +297,8 @@ public class HuabaoProtocolDecoder extends BaseProtocolDecoder {
} else if (type == MSG_TRANSPARENT) {
+ sendGeneralResponse(channel, remoteAddress, id, type, index);
+
return decodeTransparent(deviceSession, buf);
}
@@ -327,6 +332,16 @@ public class HuabaoProtocolDecoder extends BaseProtocolDecoder {
case 0x03:
position.set(Position.KEY_OBD_SPEED, buf.readUnsignedShort() * 0.1);
break;
+ case 0x56:
+ buf.readUnsignedByte(); // power level
+ position.set(Position.KEY_BATTERY_LEVEL, buf.readUnsignedByte());
+ break;
+ case 0x61:
+ position.set(Position.KEY_POWER, buf.readUnsignedShort() * 0.01);
+ break;
+ case 0x69:
+ position.set(Position.KEY_BATTERY, buf.readUnsignedShort() * 0.01);
+ break;
case 0x80:
position.set(Position.KEY_OBD_SPEED, buf.readUnsignedByte());
break;
@@ -388,6 +403,7 @@ public class HuabaoProtocolDecoder extends BaseProtocolDecoder {
int status = buf.readInt();
position.set(Position.KEY_IGNITION, BitUtil.check(status, 0));
+ position.set(Position.KEY_MOTION, BitUtil.check(status, 4));
position.set(Position.KEY_BLOCKED, BitUtil.check(status, 10));
position.set(Position.KEY_CHARGE, BitUtil.check(status, 26));
@@ -448,6 +464,7 @@ public class HuabaoProtocolDecoder extends BaseProtocolDecoder {
int subtype = buf.readUnsignedByte();
int length = buf.readUnsignedByte();
int endIndex = buf.readerIndex() + length;
+ String stringValue;
switch (subtype) {
case 0x01:
position.set(Position.KEY_ODOMETER, buf.readUnsignedInt() * 100);
@@ -455,8 +472,12 @@ public class HuabaoProtocolDecoder extends BaseProtocolDecoder {
case 0x02:
position.set(Position.KEY_FUEL_LEVEL, buf.readUnsignedShort() * 0.1);
break;
+ case 0x25:
+ position.set(Position.KEY_INPUT, buf.readUnsignedInt());
+ break;
case 0x2b:
- position.set(Position.KEY_FUEL_CONSUMPTION, buf.readUnsignedInt());
+ position.set(Position.PREFIX_ADC + 1, buf.readUnsignedShort());
+ position.set(Position.PREFIX_ADC + 2, buf.readUnsignedShort());
break;
case 0x30:
position.set(Position.KEY_RSSI, buf.readUnsignedByte());
@@ -465,12 +486,75 @@ public class HuabaoProtocolDecoder extends BaseProtocolDecoder {
position.set(Position.KEY_SATELLITES, buf.readUnsignedByte());
break;
case 0x33:
- String sentence = buf.readCharSequence(length, StandardCharsets.US_ASCII).toString();
- if (sentence.startsWith("*M00")) {
- String lockStatus = sentence.substring(8, 8 + 7);
+ stringValue = buf.readCharSequence(length, StandardCharsets.US_ASCII).toString();
+ if (stringValue.startsWith("*M00")) {
+ String lockStatus = stringValue.substring(8, 8 + 7);
position.set(Position.KEY_BATTERY, Integer.parseInt(lockStatus.substring(2, 5)) * 0.01);
}
break;
+ case 0x56:
+ position.set(Position.KEY_BATTERY_LEVEL, buf.readUnsignedByte() * 10);
+ buf.readUnsignedByte(); // reserved
+ break;
+ case 0x57:
+ int alarm = buf.readUnsignedShort();
+ position.set(Position.KEY_ALARM, BitUtil.check(alarm, 8) ? Position.ALARM_ACCELERATION : null);
+ position.set(Position.KEY_ALARM, BitUtil.check(alarm, 9) ? Position.ALARM_BRAKING : null);
+ position.set(Position.KEY_ALARM, BitUtil.check(alarm, 10) ? Position.ALARM_CORNERING : null);
+ buf.readUnsignedShort(); // external switch state
+ buf.skipBytes(4); // reserved
+ break;
+ case 0x60:
+ int event = buf.readUnsignedShort();
+ position.set(Position.KEY_EVENT, event);
+ if (event >= 0x0061 && event <= 0x0066) {
+ buf.skipBytes(6); // lock id
+ stringValue = buf.readCharSequence(8, StandardCharsets.US_ASCII).toString();
+ position.set(Position.KEY_DRIVER_UNIQUE_ID, stringValue);
+ }
+ break;
+ case 0x63:
+ for (int i = 1; i <= length / 11; i++) {
+ position.set("lock" + i + "Id", ByteBufUtil.hexDump(buf.readSlice(6)));
+ position.set("lock" + i + "Battery", buf.readUnsignedShort() * 0.001);
+ position.set("lock" + i + "Seal", buf.readUnsignedByte() == 0x31);
+ buf.readUnsignedByte(); // physical state
+ buf.readUnsignedByte(); // rssi
+ }
+ break;
+ case 0x64:
+ buf.readUnsignedInt(); // alarm serial number
+ buf.readUnsignedByte(); // alarm status
+ position.set("adasAlarm", buf.readUnsignedByte());
+ break;
+ case 0x65:
+ buf.readUnsignedInt(); // alarm serial number
+ buf.readUnsignedByte(); // alarm status
+ position.set("dmsAlarm", buf.readUnsignedByte());
+ break;
+ case 0x70:
+ buf.readUnsignedInt(); // alarm serial number
+ buf.readUnsignedByte(); // alarm status
+ switch (buf.readUnsignedByte()) {
+ case 0x01:
+ position.set(Position.KEY_ALARM, Position.ALARM_ACCELERATION);
+ break;
+ case 0x02:
+ position.set(Position.KEY_ALARM, Position.ALARM_BRAKING);
+ break;
+ case 0x03:
+ position.set(Position.KEY_ALARM, Position.ALARM_CORNERING);
+ break;
+ case 0x16:
+ position.set(Position.KEY_ALARM, Position.ALARM_ACCIDENT);
+ break;
+ default:
+ break;
+ }
+ break;
+ case 0x69:
+ position.set(Position.KEY_BATTERY, buf.readUnsignedShort() * 0.01);
+ break;
case 0x80:
buf.readUnsignedByte(); // content
endIndex = buf.writerIndex() - 2;
@@ -492,8 +576,8 @@ public class HuabaoProtocolDecoder extends BaseProtocolDecoder {
break;
case 0x94:
if (length > 0) {
- position.set(
- Position.KEY_VIN, buf.readCharSequence(length, StandardCharsets.US_ASCII).toString());
+ stringValue = buf.readCharSequence(length, StandardCharsets.US_ASCII).toString();
+ position.set(Position.KEY_VIN, stringValue);
}
break;
case 0xA7:
@@ -503,6 +587,14 @@ public class HuabaoProtocolDecoder extends BaseProtocolDecoder {
case 0xAC:
position.set(Position.KEY_ODOMETER, buf.readUnsignedInt());
break;
+ case 0xBC:
+ stringValue = buf.readCharSequence(length, StandardCharsets.US_ASCII).toString();
+ position.set("driver", stringValue.trim());
+ break;
+ case 0xBD:
+ stringValue = buf.readCharSequence(length, StandardCharsets.US_ASCII).toString();
+ position.set(Position.KEY_DRIVER_UNIQUE_ID, stringValue);
+ break;
case 0xD0:
long userStatus = buf.readUnsignedInt();
if (BitUtil.check(userStatus, 3)) {
@@ -513,7 +605,12 @@ public class HuabaoProtocolDecoder extends BaseProtocolDecoder {
position.set(Position.KEY_POWER, buf.readUnsignedShort() * 0.1);
break;
case 0xD4:
- position.set(Position.KEY_BATTERY_LEVEL, buf.readUnsignedByte());
+ case 0xE1:
+ if (length == 1) {
+ position.set(Position.KEY_BATTERY_LEVEL, buf.readUnsignedByte());
+ } else {
+ position.set(Position.KEY_DRIVER_UNIQUE_ID, String.valueOf(buf.readUnsignedInt()));
+ }
break;
case 0xD5:
if (length == 2) {
@@ -536,6 +633,9 @@ public class HuabaoProtocolDecoder extends BaseProtocolDecoder {
position.set(Position.KEY_MOTION, BitUtil.check(deviceStatus, 2));
position.set("cover", BitUtil.check(deviceStatus, 3));
break;
+ case 0xE2:
+ position.set(Position.KEY_FUEL_LEVEL, buf.readUnsignedInt() * 0.1);
+ break;
case 0xE6:
while (buf.readerIndex() < endIndex) {
int sensorIndex = buf.readUnsignedByte();
@@ -589,8 +689,8 @@ public class HuabaoProtocolDecoder extends BaseProtocolDecoder {
}
break;
case 0xED:
- String license = buf.readCharSequence(length, StandardCharsets.US_ASCII).toString().trim();
- position.set("driverLicense", license);
+ stringValue = buf.readCharSequence(length, StandardCharsets.US_ASCII).toString();
+ position.set(Position.KEY_CARD, stringValue.trim());
break;
case 0xEE:
position.set(Position.KEY_RSSI, buf.readUnsignedByte());
@@ -663,6 +763,8 @@ public class HuabaoProtocolDecoder extends BaseProtocolDecoder {
case 0xFE:
if (length == 1) {
position.set(Position.KEY_BATTERY_LEVEL, buf.readUnsignedByte());
+ } else if (length == 2) {
+ position.set(Position.KEY_POWER, buf.readUnsignedShort() * 0.1);
} else {
int mark = buf.readUnsignedByte();
if (mark == 0x7C) {
@@ -721,12 +823,15 @@ public class HuabaoProtocolDecoder extends BaseProtocolDecoder {
int battery = buf.readUnsignedByte();
if (battery <= 100) {
position.set(Position.KEY_BATTERY_LEVEL, battery);
- } else if (battery == 0xAA) {
+ } else if (battery == 0xAA || battery == 0xAB) {
position.set(Position.KEY_CHARGE, true);
}
- position.setNetwork(new Network(CellTower.fromCidLac(
- getConfig(), buf.readUnsignedInt(), buf.readUnsignedShort())));
+ long cid = buf.readUnsignedInt();
+ int lac = buf.readUnsignedShort();
+ if (cid > 0 && lac > 0) {
+ position.setNetwork(new Network(CellTower.fromCidLac(getConfig(), cid, lac)));
+ }
int product = buf.readUnsignedByte();
int status = buf.readUnsignedShort();
@@ -738,6 +843,9 @@ public class HuabaoProtocolDecoder extends BaseProtocolDecoder {
}
} else if (product == 3) {
position.set(Position.KEY_BLOCKED, BitUtil.check(status, 5));
+ if (BitUtil.check(alarm, 0)) {
+ position.set(Position.KEY_ALARM, Position.ALARM_OVERSPEED);
+ }
if (BitUtil.check(alarm, 1)) {
position.set(Position.KEY_ALARM, Position.ALARM_LOW_POWER);
}
@@ -747,10 +855,69 @@ public class HuabaoProtocolDecoder extends BaseProtocolDecoder {
if (BitUtil.check(alarm, 3)) {
position.set(Position.KEY_ALARM, Position.ALARM_LOW_BATTERY);
}
+ if (BitUtil.check(alarm, 5)) {
+ position.set(Position.KEY_ALARM, Position.ALARM_GEOFENCE_ENTER);
+ }
+ if (BitUtil.check(alarm, 6)) {
+ position.set(Position.KEY_ALARM, Position.ALARM_GEOFENCE_EXIT);
+ }
}
position.set(Position.KEY_STATUS, status);
+ while (buf.readableBytes() > 2) {
+ int id = buf.readUnsignedByte();
+ int length = buf.readUnsignedByte();
+ switch (id) {
+ case 0x02:
+ position.setAltitude(buf.readShort());
+ break;
+ case 0x10:
+ position.set("wakeSource", buf.readUnsignedByte());
+ break;
+ case 0x0A:
+ if (length == 3) {
+ buf.readUnsignedShort(); // mcc
+ buf.readUnsignedByte(); // mnc
+ } else {
+ buf.skipBytes(length);
+ }
+ break;
+ case 0x0B:
+ position.set("lockCommand", buf.readUnsignedByte());
+ if (length >= 5 && length <= 6) {
+ position.set("lockCard", buf.readUnsignedInt());
+ } else if (length >= 7) {
+ position.set("lockPassword", buf.readCharSequence(6, StandardCharsets.US_ASCII).toString());
+ }
+ if (length % 2 == 0) {
+ position.set("unlockResult", buf.readUnsignedByte());
+ }
+ break;
+ case 0x0C:
+ int x = buf.readUnsignedShort();
+ if (x > 0x8000) {
+ x -= 0x10000;
+ }
+ int y = buf.readUnsignedShort();
+ if (y > 0x8000) {
+ y -= 0x10000;
+ }
+ int z = buf.readUnsignedShort();
+ if (z > 0x8000) {
+ z -= 0x10000;
+ }
+ position.set("tilt", String.format("[%d,%d,%d]", x, y, z));
+ break;
+ case 0xFC:
+ position.set(Position.KEY_GEOFENCE, buf.readUnsignedByte());
+ break;
+ default:
+ buf.skipBytes(length);
+ break;
+ }
+ }
+
return position;
}
@@ -782,6 +949,7 @@ public class HuabaoProtocolDecoder extends BaseProtocolDecoder {
int type = buf.readUnsignedByte();
if (type == 0xF0) {
+
Position position = new Position(getProtocolName());
position.setDeviceId(deviceSession.getDeviceId());
@@ -823,6 +991,34 @@ public class HuabaoProtocolDecoder extends BaseProtocolDecoder {
case 0x0539:
position.set(Position.KEY_FUEL_CONSUMPTION, buf.readUnsignedShort() * 0.01);
break;
+ case 0x052B:
+ position.set(Position.KEY_FUEL_LEVEL, buf.readUnsignedByte());
+ break;
+ case 0x052D:
+ position.set(Position.KEY_COOLANT_TEMP, buf.readUnsignedByte() - 40);
+ break;
+ case 0x052E:
+ position.set("airTemp", buf.readUnsignedByte() - 40);
+ break;
+ case 0x0530:
+ position.set(Position.KEY_POWER, buf.readUnsignedShort() * 0.001);
+ break;
+ case 0x0535:
+ position.set(Position.KEY_OBD_SPEED, buf.readUnsignedShort() * 0.1);
+ break;
+ case 0x0536:
+ position.set(Position.KEY_RPM, buf.readUnsignedShort());
+ break;
+ case 0x053D:
+ position.set("intakePressure", buf.readUnsignedShort() * 0.1);
+ break;
+ case 0x0544:
+ position.set("liquidLevel", buf.readUnsignedByte());
+ break;
+ case 0x0547:
+ case 0x0548:
+ position.set(Position.KEY_THROTTLE, buf.readUnsignedByte());
+ break;
default:
switch (length) {
case 1:
@@ -841,15 +1037,40 @@ public class HuabaoProtocolDecoder extends BaseProtocolDecoder {
break;
}
}
+ getLastLocation(position, time);
+ decodeCoordinates(position, buf);
+ position.setTime(time);
+ break;
+ case 0x02:
+ List<String> codes = new LinkedList<>();
+ count = buf.readUnsignedShort();
+ for (int i = 0; i < count; i++) {
+ buf.readUnsignedInt(); // system id
+ int codeCount = buf.readUnsignedShort();
+ for (int j = 0; j < codeCount; j++) {
+ buf.readUnsignedInt(); // dtc
+ buf.readUnsignedInt(); // status
+ codes.add(buf.readCharSequence(
+ buf.readUnsignedShort(), StandardCharsets.US_ASCII).toString().trim());
+ }
+ }
+ position.set(Position.KEY_DTCS, String.join(" ", codes));
+ getLastLocation(position, time);
decodeCoordinates(position, buf);
position.setTime(time);
break;
case 0x03:
count = buf.readUnsignedByte();
for (int i = 0; i < count; i++) {
- int id = buf.readUnsignedShort();
+ int id = buf.readUnsignedByte();
int length = buf.readUnsignedByte();
switch (id) {
+ case 0x01:
+ position.set(Position.KEY_ALARM, Position.ALARM_POWER_RESTORED);
+ break;
+ case 0x02:
+ position.set(Position.KEY_ALARM, Position.ALARM_POWER_CUT);
+ break;
case 0x1A:
position.set(Position.KEY_ALARM, Position.ALARM_ACCELERATION);
break;
@@ -867,11 +1088,21 @@ public class HuabaoProtocolDecoder extends BaseProtocolDecoder {
case 0x23:
position.set(Position.KEY_ALARM, Position.ALARM_FATIGUE_DRIVING);
break;
+ case 0x26:
+ case 0x27:
+ case 0x28:
+ position.set(Position.KEY_ALARM, Position.ALARM_ACCIDENT);
+ break;
+ case 0x31:
+ case 0x32:
+ position.set(Position.KEY_ALARM, Position.ALARM_DOOR);
+ break;
default:
break;
}
buf.skipBytes(length);
}
+ getLastLocation(position, time);
decodeCoordinates(position, buf);
position.setTime(time);
break;
@@ -886,6 +1117,24 @@ public class HuabaoProtocolDecoder extends BaseProtocolDecoder {
}
return position;
+
+ } else if (type == 0xFF) {
+
+ Position position = new Position(getProtocolName());
+ position.setDeviceId(deviceSession.getDeviceId());
+
+ position.setValid(true);
+ position.setTime(readDate(buf, deviceSession.get(DeviceSession.KEY_TIMEZONE)));
+ position.setLatitude(buf.readInt() * 0.000001);
+ position.setLongitude(buf.readInt() * 0.000001);
+ position.setAltitude(buf.readShort());
+ position.setSpeed(UnitsConverter.knotsFromKph(buf.readUnsignedShort() * 0.1));
+ position.setCourse(buf.readUnsignedShort());
+
+ // TODO more positions and g sensor data
+
+ return position;
+
}
return null;
diff --git a/src/main/java/org/traccar/protocol/HunterProProtocol.java b/src/main/java/org/traccar/protocol/HunterProProtocol.java
index ed4289d73..64dab33b1 100644
--- a/src/main/java/org/traccar/protocol/HunterProProtocol.java
+++ b/src/main/java/org/traccar/protocol/HunterProProtocol.java
@@ -23,7 +23,7 @@ import org.traccar.PipelineBuilder;
import org.traccar.TrackerServer;
import org.traccar.config.Config;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class HunterProProtocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/IdplProtocol.java b/src/main/java/org/traccar/protocol/IdplProtocol.java
index aa1f4ff5b..1e44ad74c 100644
--- a/src/main/java/org/traccar/protocol/IdplProtocol.java
+++ b/src/main/java/org/traccar/protocol/IdplProtocol.java
@@ -23,7 +23,7 @@ import org.traccar.PipelineBuilder;
import org.traccar.TrackerServer;
import org.traccar.config.Config;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class IdplProtocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/IntellitracProtocol.java b/src/main/java/org/traccar/protocol/IntellitracProtocol.java
index b1a91cca9..a82e6a5db 100644
--- a/src/main/java/org/traccar/protocol/IntellitracProtocol.java
+++ b/src/main/java/org/traccar/protocol/IntellitracProtocol.java
@@ -22,7 +22,7 @@ import org.traccar.PipelineBuilder;
import org.traccar.TrackerServer;
import org.traccar.config.Config;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class IntellitracProtocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/IotmProtocol.java b/src/main/java/org/traccar/protocol/IotmProtocol.java
index 0d288f4bf..1631b67d8 100644
--- a/src/main/java/org/traccar/protocol/IotmProtocol.java
+++ b/src/main/java/org/traccar/protocol/IotmProtocol.java
@@ -22,7 +22,7 @@ import org.traccar.PipelineBuilder;
import org.traccar.TrackerServer;
import org.traccar.config.Config;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class IotmProtocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/IotmProtocolDecoder.java b/src/main/java/org/traccar/protocol/IotmProtocolDecoder.java
index 7bbe6c8de..d9e6670c6 100644
--- a/src/main/java/org/traccar/protocol/IotmProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/IotmProtocolDecoder.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2020 - 2022 Anton Tananaev (anton@traccar.org)
+ * Copyright 2020 - 2023 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.
@@ -17,27 +17,19 @@ package org.traccar.protocol;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufUtil;
-import io.netty.channel.Channel;
-import io.netty.handler.codec.mqtt.MqttConnectMessage;
-import io.netty.handler.codec.mqtt.MqttConnectReturnCode;
-import io.netty.handler.codec.mqtt.MqttMessage;
-import io.netty.handler.codec.mqtt.MqttMessageBuilders;
import io.netty.handler.codec.mqtt.MqttPublishMessage;
-import io.netty.handler.codec.mqtt.MqttSubscribeMessage;
-import org.traccar.BaseProtocolDecoder;
-import org.traccar.session.DeviceSession;
-import org.traccar.NetworkMessage;
+import org.traccar.BaseMqttProtocolDecoder;
import org.traccar.Protocol;
import org.traccar.helper.UnitsConverter;
import org.traccar.model.Position;
+import org.traccar.session.DeviceSession;
-import java.net.SocketAddress;
import java.nio.charset.StandardCharsets;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;
-public class IotmProtocolDecoder extends BaseProtocolDecoder {
+public class IotmProtocolDecoder extends BaseMqttProtocolDecoder {
public IotmProtocolDecoder(Protocol protocol) {
super(protocol);
@@ -236,121 +228,72 @@ public class IotmProtocolDecoder extends BaseProtocolDecoder {
@Override
protected Object decode(
- Channel channel, SocketAddress remoteAddress, Object msg) throws Exception {
-
- if (msg instanceof MqttConnectMessage) {
-
- MqttConnectMessage message = (MqttConnectMessage) msg;
+ DeviceSession deviceSession, MqttPublishMessage message) throws Exception {
- DeviceSession deviceSession = getDeviceSession(
- channel, remoteAddress, message.payload().clientIdentifier());
-
- MqttConnectReturnCode returnCode = deviceSession != null
- ? MqttConnectReturnCode.CONNECTION_ACCEPTED
- : MqttConnectReturnCode.CONNECTION_REFUSED_IDENTIFIER_REJECTED;
-
- MqttMessage response = MqttMessageBuilders.connAck().returnCode(returnCode).build();
-
- if (channel != null) {
- channel.writeAndFlush(new NetworkMessage(response, remoteAddress));
- }
+ List<Position> positions = new LinkedList<>();
- } else if (msg instanceof MqttSubscribeMessage) {
+ ByteBuf buf = message.payload();
- MqttSubscribeMessage message = (MqttSubscribeMessage) msg;
-
- MqttMessage response = MqttMessageBuilders.subAck()
- .packetId(message.variableHeader().messageId())
- .build();
-
- if (channel != null) {
- channel.writeAndFlush(new NetworkMessage(response, remoteAddress));
- }
-
- } else if (msg instanceof MqttPublishMessage) {
-
- DeviceSession deviceSession = getDeviceSession(channel, remoteAddress);
- if (deviceSession == null) {
- return null;
- }
+ buf.readUnsignedByte(); // structure version
- List<Position> positions = new LinkedList<>();
+ while (buf.readableBytes() > 1) {
+ int type = buf.readUnsignedByte();
+ int length = buf.readUnsignedShortLE();
+ ByteBuf record = buf.readSlice(length);
+ if (type == 1) {
- MqttPublishMessage message = (MqttPublishMessage) msg;
- ByteBuf buf = message.payload();
+ Position position = new Position(getProtocolName());
+ position.setDeviceId(deviceSession.getDeviceId());
+ position.setTime(new Date(record.readUnsignedIntLE() * 1000));
- buf.readUnsignedByte(); // structure version
+ while (record.readableBytes() > 0) {
+ int sensorType = record.readUnsignedByte();
+ int sensorId = record.readUnsignedShortLE();
+ if (sensorType == 14) {
- while (buf.readableBytes() > 1) {
- int type = buf.readUnsignedByte();
- int length = buf.readUnsignedShortLE();
- ByteBuf record = buf.readSlice(length);
- if (type == 1) {
+ position.setValid(true);
+ position.setLatitude(record.readFloatLE());
+ position.setLongitude(record.readFloatLE());
+ position.setSpeed(UnitsConverter.knotsFromKph(record.readUnsignedShortLE()));
- Position position = new Position(getProtocolName());
- position.setDeviceId(deviceSession.getDeviceId());
- position.setTime(new Date(record.readUnsignedIntLE() * 1000));
+ position.set(Position.KEY_HDOP, record.readUnsignedByte());
+ position.set(Position.KEY_SATELLITES, record.readUnsignedByte());
- while (record.readableBytes() > 0) {
- int sensorType = record.readUnsignedByte();
- int sensorId = record.readUnsignedShortLE();
- if (sensorType == 14) {
+ position.setCourse(record.readUnsignedShortLE());
+ position.setAltitude(record.readShortLE());
- position.setValid(true);
- position.setLatitude(record.readFloatLE());
- position.setLongitude(record.readFloatLE());
- position.setSpeed(UnitsConverter.knotsFromKph(record.readUnsignedShortLE()));
-
- position.set(Position.KEY_HDOP, record.readUnsignedByte());
- position.set(Position.KEY_SATELLITES, record.readUnsignedByte());
-
- position.setCourse(record.readUnsignedShortLE());
- position.setAltitude(record.readShortLE());
-
- } else {
-
- if (sensorType == 3) {
- continue;
- }
-
- decodeSensor(position, record, sensorType, sensorId);
+ } else {
+ if (sensorType == 3) {
+ continue;
}
- }
-
- positions.add(position);
- } else if (type == 3) {
+ decodeSensor(position, record, sensorType, sensorId);
- Position position = new Position(getProtocolName());
- position.setDeviceId(deviceSession.getDeviceId());
+ }
+ }
- getLastLocation(position, new Date(record.readUnsignedIntLE() * 1000));
+ positions.add(position);
- record.readUnsignedByte(); // function identifier
+ } else if (type == 3) {
- position.set(Position.KEY_EVENT, record.readUnsignedByte());
+ Position position = new Position(getProtocolName());
+ position.setDeviceId(deviceSession.getDeviceId());
- positions.add(position);
+ getLastLocation(position, new Date(record.readUnsignedIntLE() * 1000));
- }
- }
+ record.readUnsignedByte(); // function identifier
- buf.readUnsignedByte(); // checksum
+ position.set(Position.KEY_EVENT, record.readUnsignedByte());
- MqttMessage response = MqttMessageBuilders.pubAck()
- .packetId(message.variableHeader().packetId())
- .build();
+ positions.add(position);
- if (channel != null) {
- channel.writeAndFlush(new NetworkMessage(response, remoteAddress));
}
-
- return positions.isEmpty() ? null : positions;
-
}
- return null;
+ buf.readUnsignedByte(); // checksum
+
+ return positions.isEmpty() ? null : positions;
}
}
diff --git a/src/main/java/org/traccar/protocol/ItsProtocol.java b/src/main/java/org/traccar/protocol/ItsProtocol.java
index 5148e8ab0..7d59ea60c 100644
--- a/src/main/java/org/traccar/protocol/ItsProtocol.java
+++ b/src/main/java/org/traccar/protocol/ItsProtocol.java
@@ -23,7 +23,7 @@ import org.traccar.TrackerServer;
import org.traccar.config.Config;
import org.traccar.model.Command;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class ItsProtocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/Ivt401Protocol.java b/src/main/java/org/traccar/protocol/Ivt401Protocol.java
index 763457641..5132c7467 100644
--- a/src/main/java/org/traccar/protocol/Ivt401Protocol.java
+++ b/src/main/java/org/traccar/protocol/Ivt401Protocol.java
@@ -22,7 +22,7 @@ import org.traccar.PipelineBuilder;
import org.traccar.TrackerServer;
import org.traccar.config.Config;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class Ivt401Protocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/JidoProtocol.java b/src/main/java/org/traccar/protocol/JidoProtocol.java
index 78aa6c81c..b30cc586a 100644
--- a/src/main/java/org/traccar/protocol/JidoProtocol.java
+++ b/src/main/java/org/traccar/protocol/JidoProtocol.java
@@ -23,7 +23,7 @@ import org.traccar.PipelineBuilder;
import org.traccar.TrackerServer;
import org.traccar.config.Config;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class JidoProtocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/JpKorjarProtocol.java b/src/main/java/org/traccar/protocol/JpKorjarProtocol.java
index 30c8e9977..ae312ea3e 100644
--- a/src/main/java/org/traccar/protocol/JpKorjarProtocol.java
+++ b/src/main/java/org/traccar/protocol/JpKorjarProtocol.java
@@ -22,7 +22,7 @@ import org.traccar.PipelineBuilder;
import org.traccar.TrackerServer;
import org.traccar.config.Config;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class JpKorjarProtocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/Jt600FrameDecoder.java b/src/main/java/org/traccar/protocol/Jt600FrameDecoder.java
index bfefb94a7..f7890f814 100644
--- a/src/main/java/org/traccar/protocol/Jt600FrameDecoder.java
+++ b/src/main/java/org/traccar/protocol/Jt600FrameDecoder.java
@@ -35,7 +35,7 @@ public class Jt600FrameDecoder extends BaseFrameDecoder {
char type = (char) buf.getByte(buf.readerIndex());
if (type == '$') {
- boolean longFormat = Jt600ProtocolDecoder.isLongFormat(buf, buf.readerIndex() + 1);
+ boolean longFormat = Jt600ProtocolDecoder.isLongFormat(buf);
int length = buf.getUnsignedShort(buf.readerIndex() + (longFormat ? 8 : 7)) + 10;
if (length <= buf.readableBytes()) {
return buf.readRetainedSlice(length);
diff --git a/src/main/java/org/traccar/protocol/Jt600Protocol.java b/src/main/java/org/traccar/protocol/Jt600Protocol.java
index bf0b3379e..9dc62662f 100644
--- a/src/main/java/org/traccar/protocol/Jt600Protocol.java
+++ b/src/main/java/org/traccar/protocol/Jt600Protocol.java
@@ -22,7 +22,7 @@ import org.traccar.TrackerServer;
import org.traccar.config.Config;
import org.traccar.model.Command;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class Jt600Protocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/Jt600ProtocolDecoder.java b/src/main/java/org/traccar/protocol/Jt600ProtocolDecoder.java
index 9ed44f565..eca7e2d11 100644
--- a/src/main/java/org/traccar/protocol/Jt600ProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/Jt600ProtocolDecoder.java
@@ -86,8 +86,8 @@ public class Jt600ProtocolDecoder extends BaseProtocolDecoder {
}
- static boolean isLongFormat(ByteBuf buf, int flagIndex) {
- return buf.getUnsignedByte(flagIndex) >> 4 >= 7;
+ static boolean isLongFormat(ByteBuf buf) {
+ return buf.getUnsignedByte(buf.readerIndex() + 8) == 0;
}
static void decodeBinaryLocation(ByteBuf buf, Position position) {
@@ -105,15 +105,9 @@ public class Jt600ProtocolDecoder extends BaseProtocolDecoder {
double longitude = convertCoordinate(BcdUtil.readInteger(buf, 9));
byte flags = buf.readByte();
- position.setValid((flags & 0x1) == 0x1);
- if ((flags & 0x2) == 0) {
- latitude = -latitude;
- }
- position.setLatitude(latitude);
- if ((flags & 0x4) == 0) {
- longitude = -longitude;
- }
- position.setLongitude(longitude);
+ position.setValid(BitUtil.check(flags, 0));
+ position.setLatitude(BitUtil.check(flags, 1) ? latitude : -latitude);
+ position.setLongitude(BitUtil.check(flags, 2) ? longitude : -longitude);
position.setSpeed(BcdUtil.readInteger(buf, 2));
position.setCourse(buf.readUnsignedByte() * 2.0);
@@ -123,9 +117,9 @@ public class Jt600ProtocolDecoder extends BaseProtocolDecoder {
List<Position> positions = new LinkedList<>();
- buf.readByte(); // header
+ boolean longFormat = isLongFormat(buf);
- boolean longFormat = isLongFormat(buf, buf.readerIndex());
+ buf.readByte(); // header
String id = String.valueOf(Long.parseLong(ByteBufUtil.hexDump(buf.readSlice(5))));
DeviceSession deviceSession = getDeviceSession(channel, remoteAddress, id);
@@ -386,7 +380,7 @@ public class Jt600ProtocolDecoder extends BaseProtocolDecoder {
.expression("([AV]),") // validity
.number("(d+),") // speed
.number("(d+),") // course
- .number("d+,") // event source
+ .number("(d+),") // event source
.number("d+,") // unlock verification
.number("(d+),") // rfid
.number("d+,") // password verification
@@ -419,6 +413,8 @@ public class Jt600ProtocolDecoder extends BaseProtocolDecoder {
position.setSpeed(UnitsConverter.knotsFromMph(parser.nextDouble()));
position.setCourse(parser.nextDouble());
+ position.set("eventSource", parser.nextInt());
+
String rfid = parser.next();
if (!rfid.equals("0000000000")) {
position.set(Position.KEY_DRIVER_UNIQUE_ID, rfid);
diff --git a/src/main/java/org/traccar/protocol/KenjiProtocol.java b/src/main/java/org/traccar/protocol/KenjiProtocol.java
index 8d78c8c56..b4e610cbd 100644
--- a/src/main/java/org/traccar/protocol/KenjiProtocol.java
+++ b/src/main/java/org/traccar/protocol/KenjiProtocol.java
@@ -24,7 +24,7 @@ import org.traccar.PipelineBuilder;
import org.traccar.TrackerServer;
import org.traccar.config.Config;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class KenjiProtocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/KhdProtocol.java b/src/main/java/org/traccar/protocol/KhdProtocol.java
index 521274de5..add13ef16 100644
--- a/src/main/java/org/traccar/protocol/KhdProtocol.java
+++ b/src/main/java/org/traccar/protocol/KhdProtocol.java
@@ -22,7 +22,7 @@ import org.traccar.TrackerServer;
import org.traccar.config.Config;
import org.traccar.model.Command;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class KhdProtocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/KhdProtocolDecoder.java b/src/main/java/org/traccar/protocol/KhdProtocolDecoder.java
index d7c236c4f..e88b34478 100644
--- a/src/main/java/org/traccar/protocol/KhdProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/KhdProtocolDecoder.java
@@ -20,6 +20,7 @@ import io.netty.buffer.ByteBufUtil;
import io.netty.buffer.Unpooled;
import io.netty.channel.Channel;
import org.traccar.BaseProtocolDecoder;
+import org.traccar.helper.BufferUtil;
import org.traccar.session.DeviceSession;
import org.traccar.NetworkMessage;
import org.traccar.Protocol;
@@ -169,7 +170,9 @@ public class KhdProtocolDecoder extends BaseProtocolDecoder {
position.set(Position.KEY_FUEL_LEVEL, BitUtil.from(odometer, 16));
}
- position.set(Position.KEY_STATUS, buf.readUnsignedInt());
+ long status = buf.readUnsignedInt();
+ position.set(Position.KEY_IGNITION, BitUtil.check(status, 7 + 3 * 8));
+ position.set(Position.KEY_STATUS, status);
buf.readUnsignedShort();
buf.readUnsignedByte();
@@ -185,8 +188,7 @@ public class KhdProtocolDecoder extends BaseProtocolDecoder {
buf.readUnsignedShort(); // data length
int dataType = buf.readUnsignedByte();
-
- buf.readUnsignedByte(); // content length
+ int dataLength = buf.readUnsignedByte();
switch (dataType) {
case 0x01:
@@ -197,6 +199,20 @@ public class KhdProtocolDecoder extends BaseProtocolDecoder {
position.set(Position.PREFIX_TEMP + 1,
buf.readUnsignedByte() * 100 + buf.readUnsignedByte());
break;
+ case 0x05:
+ int sign = buf.readUnsignedByte();
+ switch (sign) {
+ case 1:
+ position.set("sign", true);
+ break;
+ case 2:
+ position.set("sign", false);
+ break;
+ default:
+ break;
+ }
+ position.set(Position.KEY_DRIVER_UNIQUE_ID, BufferUtil.readString(buf, dataLength - 1));
+ break;
case 0x18:
for (int i = 1; i <= 4; i++) {
double value = buf.readUnsignedShort();
@@ -205,6 +221,9 @@ public class KhdProtocolDecoder extends BaseProtocolDecoder {
}
}
break;
+ case 0x20:
+ position.set(Position.KEY_BATTERY_LEVEL, buf.readUnsignedByte());
+ break;
case 0x23:
Network network = new Network();
int count = buf.readUnsignedByte();
diff --git a/src/main/java/org/traccar/protocol/L100Protocol.java b/src/main/java/org/traccar/protocol/L100Protocol.java
index 0edea6095..fa6d1b07e 100644
--- a/src/main/java/org/traccar/protocol/L100Protocol.java
+++ b/src/main/java/org/traccar/protocol/L100Protocol.java
@@ -22,7 +22,7 @@ import org.traccar.PipelineBuilder;
import org.traccar.TrackerServer;
import org.traccar.config.Config;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class L100Protocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/LacakProtocol.java b/src/main/java/org/traccar/protocol/LacakProtocol.java
index bbebd51ed..ddaf5078d 100644
--- a/src/main/java/org/traccar/protocol/LacakProtocol.java
+++ b/src/main/java/org/traccar/protocol/LacakProtocol.java
@@ -23,7 +23,7 @@ import org.traccar.PipelineBuilder;
import org.traccar.TrackerServer;
import org.traccar.config.Config;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class LacakProtocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/LacakProtocolDecoder.java b/src/main/java/org/traccar/protocol/LacakProtocolDecoder.java
index 809fafc90..66aab3490 100644
--- a/src/main/java/org/traccar/protocol/LacakProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/LacakProtocolDecoder.java
@@ -24,8 +24,8 @@ import org.traccar.Protocol;
import org.traccar.helper.DateUtil;
import org.traccar.model.Position;
-import javax.json.Json;
-import javax.json.JsonObject;
+import jakarta.json.Json;
+import jakarta.json.JsonObject;
import java.io.StringReader;
import java.net.SocketAddress;
import java.nio.charset.StandardCharsets;
diff --git a/src/main/java/org/traccar/protocol/LaipacProtocol.java b/src/main/java/org/traccar/protocol/LaipacProtocol.java
index 249d3bcbe..65b1a57e9 100644
--- a/src/main/java/org/traccar/protocol/LaipacProtocol.java
+++ b/src/main/java/org/traccar/protocol/LaipacProtocol.java
@@ -24,7 +24,7 @@ import org.traccar.TrackerServer;
import org.traccar.config.Config;
import org.traccar.model.Command;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class LaipacProtocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/LaipacProtocolDecoder.java b/src/main/java/org/traccar/protocol/LaipacProtocolDecoder.java
index e9570ee11..343d42e09 100644
--- a/src/main/java/org/traccar/protocol/LaipacProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/LaipacProtocolDecoder.java
@@ -28,6 +28,7 @@ import org.traccar.helper.PatternBuilder;
import org.traccar.model.CellTower;
import org.traccar.model.Network;
import org.traccar.model.Position;
+import org.traccar.helper.BitUtil;
import java.net.SocketAddress;
import java.util.regex.Pattern;
@@ -108,19 +109,31 @@ public class LaipacProtocolDecoder extends BaseProtocolDecoder {
}
}
- private String decodeEvent(String event, Position position) {
+ private String decodeEvent(String event, Position position, String model) {
if (event.length() == 1) {
char inputStatus = event.charAt(0);
if (inputStatus >= 'A' && inputStatus <= 'D') {
int inputStatusInt = inputStatus - 'A';
- position.set(Position.PREFIX_IN + 1, inputStatusInt & 1);
- position.set(Position.PREFIX_IN + 2, inputStatusInt & 2);
+ position.set(Position.PREFIX_IN + 1, (boolean) BitUtil.check(inputStatusInt, 0));
+ position.set(Position.PREFIX_IN + 2, (boolean) BitUtil.check(inputStatusInt, 1));
+ if ("SF-Lite".equals(model)) {
+ position.set(Position.PREFIX_IN + 3, false);
+ }
+ return null;
+ } else if (inputStatus >= 'O' && inputStatus <= 'R') {
+ int inputStatusInt = inputStatus - 'O';
+ position.set(Position.PREFIX_IN + 1, (boolean) BitUtil.check(inputStatusInt, 0));
+ position.set(Position.PREFIX_IN + 2, (boolean) BitUtil.check(inputStatusInt, 1));
+ if ("SF-Lite".equals(model)) {
+ position.set(Position.PREFIX_IN + 3, true);
+ }
return null;
}
}
return event;
+
}
private void sendEventResponse(
@@ -132,6 +145,9 @@ public class LaipacProtocolDecoder extends BaseProtocolDecoder {
case "3":
responseCode = "d";
break;
+ case "M":
+ responseCode = "m";
+ break;
case "S":
case "T":
responseCode = "t";
@@ -209,6 +225,8 @@ public class LaipacProtocolDecoder extends BaseProtocolDecoder {
return null;
}
+ String model = getDeviceModel(deviceSession);
+
Position position = new Position(getProtocolName());
position.setDeviceId(deviceSession.getDeviceId());
@@ -230,12 +248,17 @@ public class LaipacProtocolDecoder extends BaseProtocolDecoder {
String event = parser.next();
position.set(Position.KEY_ALARM, decodeAlarm(event));
- position.set(Position.KEY_EVENT, decodeEvent(event, position));
+ position.set(Position.KEY_EVENT, decodeEvent(event, position, model));
position.set(Position.KEY_BATTERY, Double.parseDouble(parser.next().replaceAll("\\.", "")) * 0.001);
position.set(Position.KEY_ODOMETER, parser.nextDouble() * 1000);
position.set(Position.KEY_GPS, parser.nextInt());
position.set(Position.PREFIX_ADC + 1, parser.nextDouble() * 0.001);
- position.set(Position.PREFIX_ADC + 2, parser.nextDouble() * 0.001);
+
+ if ("AVL110".equals(model) || "AVL120".equals(model)) {
+ position.set(Position.PREFIX_ADC + 2, parser.nextDouble() * 0.001);
+ } else {
+ parser.next();
+ }
Integer lac = parser.nextHexInt();
Integer cid = parser.nextHexInt();
diff --git a/src/main/java/org/traccar/protocol/LeafSpyProtocol.java b/src/main/java/org/traccar/protocol/LeafSpyProtocol.java
index 7e13e23d0..9e167e7ba 100644
--- a/src/main/java/org/traccar/protocol/LeafSpyProtocol.java
+++ b/src/main/java/org/traccar/protocol/LeafSpyProtocol.java
@@ -24,7 +24,7 @@ import org.traccar.PipelineBuilder;
import org.traccar.TrackerServer;
import org.traccar.config.Config;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class LeafSpyProtocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/M2cProtocol.java b/src/main/java/org/traccar/protocol/M2cProtocol.java
index a23ea0f57..8abc30f60 100644
--- a/src/main/java/org/traccar/protocol/M2cProtocol.java
+++ b/src/main/java/org/traccar/protocol/M2cProtocol.java
@@ -23,7 +23,7 @@ import org.traccar.PipelineBuilder;
import org.traccar.TrackerServer;
import org.traccar.config.Config;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class M2cProtocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/M2mProtocol.java b/src/main/java/org/traccar/protocol/M2mProtocol.java
index 6809d800c..03a069d66 100644
--- a/src/main/java/org/traccar/protocol/M2mProtocol.java
+++ b/src/main/java/org/traccar/protocol/M2mProtocol.java
@@ -21,7 +21,7 @@ import org.traccar.PipelineBuilder;
import org.traccar.TrackerServer;
import org.traccar.config.Config;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class M2mProtocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/MaestroProtocol.java b/src/main/java/org/traccar/protocol/MaestroProtocol.java
index 38a67f9a4..29f0b8897 100644
--- a/src/main/java/org/traccar/protocol/MaestroProtocol.java
+++ b/src/main/java/org/traccar/protocol/MaestroProtocol.java
@@ -23,7 +23,7 @@ import org.traccar.PipelineBuilder;
import org.traccar.TrackerServer;
import org.traccar.config.Config;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class MaestroProtocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/ManPowerProtocol.java b/src/main/java/org/traccar/protocol/ManPowerProtocol.java
index 492e86605..ba2414ca7 100644
--- a/src/main/java/org/traccar/protocol/ManPowerProtocol.java
+++ b/src/main/java/org/traccar/protocol/ManPowerProtocol.java
@@ -23,7 +23,7 @@ import org.traccar.PipelineBuilder;
import org.traccar.TrackerServer;
import org.traccar.config.Config;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class ManPowerProtocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/Mavlink2Protocol.java b/src/main/java/org/traccar/protocol/Mavlink2Protocol.java
index cf65a2db3..916fb7467 100644
--- a/src/main/java/org/traccar/protocol/Mavlink2Protocol.java
+++ b/src/main/java/org/traccar/protocol/Mavlink2Protocol.java
@@ -21,7 +21,7 @@ import org.traccar.PipelineBuilder;
import org.traccar.TrackerServer;
import org.traccar.config.Config;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class Mavlink2Protocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/MegastekProtocol.java b/src/main/java/org/traccar/protocol/MegastekProtocol.java
index 10215eb7c..9f8937f01 100644
--- a/src/main/java/org/traccar/protocol/MegastekProtocol.java
+++ b/src/main/java/org/traccar/protocol/MegastekProtocol.java
@@ -22,7 +22,7 @@ import org.traccar.PipelineBuilder;
import org.traccar.TrackerServer;
import org.traccar.config.Config;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class MegastekProtocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/MeiligaoProtocol.java b/src/main/java/org/traccar/protocol/MeiligaoProtocol.java
index 492094ce3..d86a00fb3 100644
--- a/src/main/java/org/traccar/protocol/MeiligaoProtocol.java
+++ b/src/main/java/org/traccar/protocol/MeiligaoProtocol.java
@@ -21,7 +21,7 @@ import org.traccar.TrackerServer;
import org.traccar.config.Config;
import org.traccar.model.Command;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class MeiligaoProtocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/MeiligaoProtocolDecoder.java b/src/main/java/org/traccar/protocol/MeiligaoProtocolDecoder.java
index f3b56973a..1f8c4d2da 100644
--- a/src/main/java/org/traccar/protocol/MeiligaoProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/MeiligaoProtocolDecoder.java
@@ -282,7 +282,7 @@ public class MeiligaoProtocolDecoder extends BaseProtocolDecoder {
position.set(Position.KEY_RSSI, parser.nextHexInt());
position.set(Position.KEY_ODOMETER, parser.nextHexLong());
position.set(Position.KEY_SATELLITES, parser.nextHexInt());
- position.set("driverLicense", parser.next());
+ position.set(Position.KEY_CARD, parser.next());
position.set(Position.KEY_ODOMETER, parser.nextLong());
position.set(Position.KEY_DRIVER_UNIQUE_ID, parser.next());
diff --git a/src/main/java/org/traccar/protocol/MeiligaoProtocolEncoder.java b/src/main/java/org/traccar/protocol/MeiligaoProtocolEncoder.java
index 5859d91ce..6d3b4f7e9 100644
--- a/src/main/java/org/traccar/protocol/MeiligaoProtocolEncoder.java
+++ b/src/main/java/org/traccar/protocol/MeiligaoProtocolEncoder.java
@@ -24,7 +24,6 @@ import org.traccar.helper.Checksum;
import org.traccar.helper.DataConverter;
import org.traccar.helper.model.AttributeUtil;
import org.traccar.model.Command;
-import org.traccar.model.Device;
import java.nio.charset.StandardCharsets;
import java.util.Set;
@@ -64,7 +63,7 @@ public class MeiligaoProtocolEncoder extends BaseProtocolEncoder {
int outputCount;
int outputType;
- String model = getCacheManager().getObject(Device.class, deviceId).getModel();
+ String model = getDeviceModel(deviceId);
if (model != null && Set.of("TK510", "GT08", "TK208", "TK228", "MT05").contains(model)) {
outputCount = 5;
diff --git a/src/main/java/org/traccar/protocol/MeitrackProtocol.java b/src/main/java/org/traccar/protocol/MeitrackProtocol.java
index c6eba8fe1..4109b22c9 100644
--- a/src/main/java/org/traccar/protocol/MeitrackProtocol.java
+++ b/src/main/java/org/traccar/protocol/MeitrackProtocol.java
@@ -22,7 +22,7 @@ import org.traccar.TrackerServer;
import org.traccar.config.Config;
import org.traccar.model.Command;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class MeitrackProtocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/MeitrackProtocolDecoder.java b/src/main/java/org/traccar/protocol/MeitrackProtocolDecoder.java
index 343141dca..88b6380a5 100644
--- a/src/main/java/org/traccar/protocol/MeitrackProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/MeitrackProtocolDecoder.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2012 - 2022 Anton Tananaev (anton@traccar.org)
+ * Copyright 2012 - 2023 Anton Tananaev (anton@traccar.org)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,10 +16,10 @@
package org.traccar.protocol;
import io.netty.buffer.ByteBuf;
+import io.netty.buffer.ByteBufUtil;
import io.netty.buffer.Unpooled;
import io.netty.channel.Channel;
import org.traccar.BaseProtocolDecoder;
-import org.traccar.model.Device;
import org.traccar.session.DeviceSession;
import org.traccar.NetworkMessage;
import org.traccar.Protocol;
@@ -30,12 +30,14 @@ import org.traccar.helper.UnitsConverter;
import org.traccar.model.CellTower;
import org.traccar.model.Network;
import org.traccar.model.Position;
+import org.traccar.model.WifiAccessPoint;
import java.net.SocketAddress;
import java.nio.charset.StandardCharsets;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;
+import java.util.Objects;
import java.util.regex.Pattern;
public class MeitrackProtocolDecoder extends BaseProtocolDecoder {
@@ -204,11 +206,7 @@ public class MeitrackProtocolDecoder extends BaseProtocolDecoder {
position.set(Position.PREFIX_ADC + i, parser.nextHexInt());
}
- String model = getCacheManager().getObject(Device.class, deviceSession.getDeviceId()).getModel();
- if (model == null) {
- model = "";
- }
- switch (model.toUpperCase()) {
+ switch (Objects.requireNonNullElse(getDeviceModel(deviceSession), "").toUpperCase()) {
case "MVT340":
case "MVT380":
position.set(Position.KEY_BATTERY, parser.nextHexInt() * 3.0 * 2.0 / 1024.0);
@@ -394,6 +392,8 @@ public class MeitrackProtocolDecoder extends BaseProtocolDecoder {
Position position = new Position(getProtocolName());
position.setDeviceId(deviceSession.getDeviceId());
+ Network network = new Network();
+
buf.readUnsignedShortLE(); // length
buf.readUnsignedShortLE(); // index
@@ -420,6 +420,12 @@ public class MeitrackProtocolDecoder extends BaseProtocolDecoder {
case 0x15:
position.set(Position.KEY_INPUT, buf.readUnsignedByte());
break;
+ case 0x47:
+ int lockState = buf.readUnsignedByte();
+ if (lockState > 0) {
+ position.set(Position.KEY_LOCK, lockState == 2);
+ }
+ break;
case 0x97:
position.set(Position.KEY_THROTTLE, buf.readUnsignedByte());
break;
@@ -455,12 +461,18 @@ public class MeitrackProtocolDecoder extends BaseProtocolDecoder {
case 0x16:
position.set(Position.PREFIX_ADC + 1, buf.readUnsignedShortLE() * 0.01);
break;
+ case 0x17:
+ position.set(Position.PREFIX_ADC + 2, buf.readUnsignedShortLE() * 0.01);
+ break;
case 0x19:
position.set(Position.KEY_BATTERY, buf.readUnsignedShortLE() * 0.01);
break;
case 0x1A:
position.set(Position.KEY_POWER, buf.readUnsignedShortLE() * 0.01);
break;
+ case 0x29:
+ position.set(Position.KEY_FUEL_LEVEL, buf.readUnsignedShortLE() * 0.01);
+ break;
case 0x40:
position.set(Position.KEY_EVENT, buf.readUnsignedShortLE());
break;
@@ -504,18 +516,26 @@ public class MeitrackProtocolDecoder extends BaseProtocolDecoder {
position.setTime(new Date((946684800 + buf.readUnsignedIntLE()) * 1000)); // 2000-01-01
break;
case 0x0C:
- case 0x9B:
position.set(Position.KEY_ODOMETER, buf.readUnsignedIntLE());
break;
case 0x0D:
position.set("runtime", buf.readUnsignedIntLE());
break;
+ case 0x25:
+ position.set(Position.KEY_DRIVER_UNIQUE_ID, String.valueOf(buf.readUnsignedIntLE()));
+ break;
+ case 0x9B:
+ position.set(Position.KEY_OBD_ODOMETER, buf.readUnsignedIntLE());
+ break;
case 0xA0:
position.set(Position.KEY_FUEL_USED, buf.readUnsignedIntLE() * 0.001);
break;
case 0xA2:
position.set(Position.KEY_FUEL_CONSUMPTION, buf.readUnsignedIntLE() * 0.01);
break;
+ case 0xFEF4:
+ position.set(Position.KEY_HOURS, buf.readUnsignedIntLE() * 60000);
+ break;
default:
buf.readUnsignedIntLE();
break;
@@ -528,6 +548,28 @@ public class MeitrackProtocolDecoder extends BaseProtocolDecoder {
int id = extension ? buf.readUnsignedShort() : buf.readUnsignedByte();
int length = buf.readUnsignedByte();
switch (id) {
+ case 0x1D:
+ case 0x1E:
+ case 0x1F:
+ case 0x20:
+ case 0x21:
+ case 0x22:
+ case 0x23:
+ case 0x24:
+ case 0x25:
+ String wifiMac = ByteBufUtil.hexDump(buf.readSlice(6)).replaceAll("(..)", "$1:");
+ network.addWifiAccessPoint(WifiAccessPoint.from(
+ wifiMac.substring(0, wifiMac.length() - 1), buf.readShortLE()));
+ break;
+ case 0x0E:
+ case 0x0F:
+ case 0x10:
+ case 0x12:
+ case 0x13:
+ network.addCellTower(CellTower.from(
+ buf.readUnsignedShortLE(), buf.readUnsignedShortLE(),
+ buf.readUnsignedShortLE(), buf.readUnsignedIntLE(), buf.readShortLE()));
+ break;
case 0x2A:
case 0x2B:
case 0x2C:
@@ -539,17 +581,48 @@ public class MeitrackProtocolDecoder extends BaseProtocolDecoder {
buf.readUnsignedByte(); // label
position.set(Position.PREFIX_TEMP + (id - 0x2A), buf.readShortLE() * 0.01);
break;
+ case 0x4B:
+ buf.skipBytes(length); // network information
+ break;
case 0xFE31:
buf.readUnsignedByte(); // alarm protocol
buf.readUnsignedByte(); // alarm type
buf.skipBytes(length - 2);
break;
+ case 0xFE73:
+ buf.readUnsignedByte(); // version
+ position.set(
+ "tagName",
+ buf.readCharSequence(buf.readUnsignedByte(), StandardCharsets.US_ASCII).toString());
+ buf.skipBytes(6); // mac
+ position.set("tagBattery", buf.readUnsignedByte());
+ position.set("tagTemp", buf.readUnsignedShortLE() / 256.0);
+ position.set("tagHumidity", buf.readUnsignedShortLE() / 256.0);
+ buf.readUnsignedShortLE(); // high temperature threshold
+ buf.readUnsignedShortLE(); // low temperature threshold
+ buf.readUnsignedShortLE(); // high humidity threshold
+ buf.readUnsignedShortLE(); // low humidity threshold
+ break;
+ case 0xFEA8:
+ for (int k = 1; k <= 3; k++) {
+ if (buf.readUnsignedByte() > 0) {
+ String key = k == 1 ? Position.KEY_BATTERY_LEVEL : "battery" + k + "Level";
+ position.set(key, buf.readUnsignedByte());
+ } else {
+ buf.readUnsignedByte();
+ }
+ }
+ buf.readUnsignedByte(); // battery alert
+ break;
default:
buf.skipBytes(length);
break;
}
}
+ if (network.getCellTowers() != null || network.getWifiAccessPoints() != null) {
+ position.setNetwork(network);
+ }
positions.add(position);
}
@@ -624,6 +697,13 @@ public class MeitrackProtocolDecoder extends BaseProtocolDecoder {
photo = Unpooled.buffer();
requestPhotoPacket(channel, remoteAddress, imei, "camera_picture.jpg", 0);
return null;
+ case "D82":
+ Position position = new Position(getProtocolName());
+ position.setDeviceId(getDeviceSession(channel, remoteAddress, imei).getDeviceId());
+ getLastLocation(position, null);
+ String result = buf.toString(index + 1, buf.writerIndex() - index - 4, StandardCharsets.US_ASCII);
+ position.set(Position.KEY_RESULT, result);
+ return position;
case "CCC":
return decodeBinaryC(channel, remoteAddress, buf);
case "CCE":
diff --git a/src/main/java/org/traccar/protocol/MictrackProtocol.java b/src/main/java/org/traccar/protocol/MictrackProtocol.java
index ccbc4db4c..08bbe0c82 100644
--- a/src/main/java/org/traccar/protocol/MictrackProtocol.java
+++ b/src/main/java/org/traccar/protocol/MictrackProtocol.java
@@ -22,7 +22,7 @@ import org.traccar.PipelineBuilder;
import org.traccar.TrackerServer;
import org.traccar.config.Config;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class MictrackProtocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/MilesmateProtocol.java b/src/main/java/org/traccar/protocol/MilesmateProtocol.java
index 59212e791..607dfc5bf 100644
--- a/src/main/java/org/traccar/protocol/MilesmateProtocol.java
+++ b/src/main/java/org/traccar/protocol/MilesmateProtocol.java
@@ -23,7 +23,7 @@ import org.traccar.PipelineBuilder;
import org.traccar.TrackerServer;
import org.traccar.config.Config;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class MilesmateProtocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/MiniFinderProtocol.java b/src/main/java/org/traccar/protocol/MiniFinderProtocol.java
index 44599accc..1cb2a0007 100644
--- a/src/main/java/org/traccar/protocol/MiniFinderProtocol.java
+++ b/src/main/java/org/traccar/protocol/MiniFinderProtocol.java
@@ -24,7 +24,7 @@ import org.traccar.TrackerServer;
import org.traccar.config.Config;
import org.traccar.model.Command;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class MiniFinderProtocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/MiniFinderProtocolDecoder.java b/src/main/java/org/traccar/protocol/MiniFinderProtocolDecoder.java
index f2e5eb905..1fdb1ece0 100644
--- a/src/main/java/org/traccar/protocol/MiniFinderProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/MiniFinderProtocolDecoder.java
@@ -143,7 +143,7 @@ public class MiniFinderProtocolDecoder extends BaseProtocolDecoder {
}
DeviceSession deviceSession = getDeviceSession(channel, remoteAddress);
- if (deviceSession == null || !sentence.matches("![35A-D],.*")) {
+ if (deviceSession == null || !sentence.matches("![345A-D],.*")) {
return null;
}
@@ -161,6 +161,20 @@ public class MiniFinderProtocolDecoder extends BaseProtocolDecoder {
return position;
+ } else if (type.equals("4")) {
+
+ String[] values = sentence.split(",");
+
+ getLastLocation(position, null);
+
+ for (int i = 1; i <= 3; i++) {
+ if (!values[i + 1].isEmpty()) {
+ position.set("phone" + i, values[i + 1]);
+ }
+ }
+
+ return position;
+
} else if (type.equals("5")) {
String[] values = sentence.split(",");
diff --git a/src/main/java/org/traccar/protocol/Minifinder2Protocol.java b/src/main/java/org/traccar/protocol/Minifinder2Protocol.java
index 5499a274e..082b9146d 100644
--- a/src/main/java/org/traccar/protocol/Minifinder2Protocol.java
+++ b/src/main/java/org/traccar/protocol/Minifinder2Protocol.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2019 - 2021 Anton Tananaev (anton@traccar.org)
+ * Copyright 2019 - 2023 Anton Tananaev (anton@traccar.org)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -20,19 +20,24 @@ import org.traccar.BaseProtocol;
import org.traccar.PipelineBuilder;
import org.traccar.TrackerServer;
import org.traccar.config.Config;
+import org.traccar.model.Command;
import java.nio.ByteOrder;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class Minifinder2Protocol extends BaseProtocol {
@Inject
public Minifinder2Protocol(Config config) {
+ setSupportedDataCommands(
+ Command.TYPE_FIRMWARE_UPDATE,
+ Command.TYPE_CONFIGURATION);
addServer(new TrackerServer(config, getName(), false) {
@Override
protected void addProtocolHandlers(PipelineBuilder pipeline, Config config) {
- pipeline.addLast(new LengthFieldBasedFrameDecoder(ByteOrder.LITTLE_ENDIAN, 1200, 2, 2, 4, 0, true));
+ pipeline.addLast(new LengthFieldBasedFrameDecoder(ByteOrder.LITTLE_ENDIAN, 2048, 2, 2, 4, 0, true));
+ pipeline.addLast(new Minifinder2ProtocolEncoder(Minifinder2Protocol.this));
pipeline.addLast(new Minifinder2ProtocolDecoder(Minifinder2Protocol.this));
}
});
diff --git a/src/main/java/org/traccar/protocol/Minifinder2ProtocolDecoder.java b/src/main/java/org/traccar/protocol/Minifinder2ProtocolDecoder.java
index 0b08badb8..64373e344 100644
--- a/src/main/java/org/traccar/protocol/Minifinder2ProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/Minifinder2ProtocolDecoder.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2019 - 2022 Anton Tananaev (anton@traccar.org)
+ * Copyright 2019 - 2024 Anton Tananaev (anton@traccar.org)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -20,6 +20,7 @@ import io.netty.buffer.ByteBufUtil;
import io.netty.buffer.Unpooled;
import io.netty.channel.Channel;
import org.traccar.BaseProtocolDecoder;
+import org.traccar.helper.BufferUtil;
import org.traccar.session.DeviceSession;
import org.traccar.NetworkMessage;
import org.traccar.Protocol;
@@ -48,6 +49,8 @@ public class Minifinder2ProtocolDecoder extends BaseProtocolDecoder {
public static final int MSG_DATA = 0x01;
public static final int MSG_CONFIGURATION = 0x02;
public static final int MSG_SERVICES = 0x03;
+ public static final int MSG_SYSTEM_CONTROL = 0x04;
+ public static final int MSG_FIRMWARE = 0x7E;
public static final int MSG_RESPONSE = 0x7F;
private String decodeAlarm(long code) {
@@ -146,14 +149,13 @@ public class Minifinder2ProtocolDecoder extends BaseProtocolDecoder {
int type = buf.readUnsignedByte();
if (BitUtil.check(flags, 4)) {
- sendResponse(channel, remoteAddress, index, type, buf);
+ sendResponse(channel, remoteAddress, index, type, buf.slice());
}
- if (type == MSG_DATA) {
+ if (type == MSG_DATA || type == MSG_SERVICES) {
List<Position> positions = new LinkedList<>();
Set<Integer> keys = new HashSet<>();
- boolean hasLocation = false;
Position position = new Position(getProtocolName());
DeviceSession deviceSession = null;
@@ -163,12 +165,8 @@ public class Minifinder2ProtocolDecoder extends BaseProtocolDecoder {
int key = buf.readUnsignedByte();
if (keys.contains(key)) {
- if (!hasLocation) {
- getLastLocation(position, null);
- }
positions.add(position);
keys.clear();
- hasLocation = false;
position = new Position(getProtocolName());
}
keys.add(key);
@@ -177,8 +175,9 @@ public class Minifinder2ProtocolDecoder extends BaseProtocolDecoder {
case 0x01:
deviceSession = getDeviceSession(
channel, remoteAddress, buf.readCharSequence(15, StandardCharsets.US_ASCII).toString());
-
- position.setDeviceId(deviceSession.getDeviceId());
+ if (deviceSession == null) {
+ return null;
+ }
break;
case 0x02:
long alarm = buf.readUnsignedIntLE();
@@ -192,7 +191,6 @@ public class Minifinder2ProtocolDecoder extends BaseProtocolDecoder {
position.set(Position.KEY_BATTERY, buf.readUnsignedShortLE() * 0.001);
break;
case 0x20:
- hasLocation = true;
position.setLatitude(buf.readIntLE() * 0.0000001);
position.setLongitude(buf.readIntLE() * 0.0000001);
position.setSpeed(UnitsConverter.knotsFromKph(buf.readUnsignedShortLE()));
@@ -232,11 +230,18 @@ public class Minifinder2ProtocolDecoder extends BaseProtocolDecoder {
position.setLatitude(buf.readIntLE() * 0.0000001);
position.setLongitude(buf.readIntLE() * 0.0000001);
position.setValid(true);
- hasLocation = true;
break;
case 0x24:
position.setTime(new Date(buf.readUnsignedIntLE() * 1000));
long status = buf.readUnsignedIntLE();
+ if (BitUtil.check(status, 4)) {
+ position.set(Position.KEY_CHARGE, true);
+ }
+ if (BitUtil.check(status, 7)) {
+ position.set(Position.KEY_ARCHIVE, true);
+ }
+ position.set(Position.KEY_MOTION, BitUtil.check(status, 9));
+ position.set(Position.KEY_RSSI, BitUtil.between(status, 19, 24));
position.set(Position.KEY_BATTERY_LEVEL, BitUtil.from(status, 24));
position.set(Position.KEY_STATUS, status);
break;
@@ -249,7 +254,6 @@ public class Minifinder2ProtocolDecoder extends BaseProtocolDecoder {
position.setLatitude(buf.readIntLE() * 0.0000001);
position.setLongitude(buf.readIntLE() * 0.0000001);
position.setValid(true);
- hasLocation = true;
}
if (BitUtil.check(beaconFlags, 6)) {
position.set("description", buf.readCharSequence(
@@ -263,7 +267,6 @@ public class Minifinder2ProtocolDecoder extends BaseProtocolDecoder {
position.setLatitude(buf.readIntLE() * 0.0000001);
position.setLongitude(buf.readIntLE() * 0.0000001);
position.setValid(true);
- hasLocation = true;
break;
case 0x30:
buf.readUnsignedIntLE(); // timestamp
@@ -277,6 +280,14 @@ public class Minifinder2ProtocolDecoder extends BaseProtocolDecoder {
i += 1;
}
break;
+ case 0x37:
+ buf.readUnsignedIntLE(); // timestamp
+ long barking = buf.readUnsignedIntLE();
+ if (BitUtil.check(barking, 31)) {
+ position.set("barkStop", true);
+ }
+ position.set("barkCount", BitUtil.to(barking, 31));
+ break;
case 0x40:
buf.readUnsignedIntLE(); // timestamp
int heartRate = buf.readUnsignedByte();
@@ -290,14 +301,14 @@ public class Minifinder2ProtocolDecoder extends BaseProtocolDecoder {
buf.readerIndex(endIndex);
}
- if (!hasLocation) {
- getLastLocation(position, null);
- }
positions.add(position);
if (deviceSession != null) {
for (Position p : positions) {
p.setDeviceId(deviceSession.getDeviceId());
+ if (!p.getValid() && !p.hasAttribute(Position.KEY_HDOP)) {
+ getLastLocation(p, null);
+ }
}
} else {
return null;
@@ -305,9 +316,195 @@ public class Minifinder2ProtocolDecoder extends BaseProtocolDecoder {
return positions;
+ } else if (type == MSG_CONFIGURATION) {
+
+ return decodeConfiguration(channel, remoteAddress, buf);
+
+ } else if (type == MSG_RESPONSE) {
+
+ DeviceSession deviceSession = getDeviceSession(channel, remoteAddress);
+ if (deviceSession == null) {
+ return null;
+ }
+
+ Position position = new Position(getProtocolName());
+ position.setDeviceId(deviceSession.getDeviceId());
+
+ getLastLocation(position, null);
+
+ buf.readUnsignedByte(); // length
+ position.set(Position.KEY_RESULT, String.valueOf(buf.readUnsignedByte()));
+
+ return position;
+
}
return null;
}
+ private Position decodeConfiguration(Channel channel, SocketAddress remoteAddress, ByteBuf buf) {
+
+ DeviceSession deviceSession = getDeviceSession(channel, remoteAddress);
+ if (deviceSession == null) {
+ return null;
+ }
+
+ Position position = new Position(getProtocolName());
+ position.setDeviceId(deviceSession.getDeviceId());
+
+ getLastLocation(position, null);
+
+ while (buf.isReadable()) {
+ int length = buf.readUnsignedByte() - 1;
+ int endIndex = buf.readerIndex() + length + 1;
+ int key = buf.readUnsignedByte();
+
+ switch (key) {
+ case 0x01:
+ position.set("moduleNumber", buf.readUnsignedInt());
+ break;
+ case 0x02:
+ position.set(Position.KEY_VERSION_FW, String.valueOf(buf.readUnsignedInt()));
+ break;
+ case 0x03:
+ position.set("imei", buf.readCharSequence(length, StandardCharsets.US_ASCII).toString());
+ break;
+ case 0x04:
+ position.set(Position.KEY_ICCID, BufferUtil.readString(buf, length));
+ break;
+ case 0x05:
+ position.set("bleMac", ByteBufUtil.hexDump(buf.readSlice(length)));
+ break;
+ case 0x06:
+ position.set("settingTime", buf.readUnsignedInt());
+ break;
+ case 0x07:
+ position.set("runTimes", buf.readUnsignedInt());
+ break;
+ case 0x0A:
+ position.set("interval", buf.readUnsignedMedium());
+ position.set("petMode", buf.readUnsignedByte());
+ break;
+ case 0x0D:
+ position.set("passwordProtect", buf.readUnsignedInt());
+ break;
+ case 0x0E:
+ position.set("timeZone", (int) buf.readByte());
+ break;
+ case 0x0F:
+ position.set("enableControl", buf.readUnsignedInt());
+ break;
+ case 0x13:
+ position.set("deviceName", BufferUtil.readString(buf, length));
+ break;
+ case 0x14:
+ position.set(Position.KEY_BATTERY_LEVEL, buf.readUnsignedByte());
+ position.set(Position.KEY_BATTERY, buf.readUnsignedShort() * 0.001);
+ break;
+ case 0x15:
+ position.set("bleLatitude", buf.readIntLE() * 0.0000001);
+ position.set("bleLongitude", buf.readIntLE() * 0.0000001);
+ position.set("bleLocation", BufferUtil.readString(buf, length - 8));
+ break;
+ case 0x17:
+ position.set("gpsUrl", BufferUtil.readString(buf, length));
+ break;
+ case 0x18:
+ position.set("lbsUrl", BufferUtil.readString(buf, length));
+ break;
+ case 0x1A:
+ position.set("firmware", BufferUtil.readString(buf, length));
+ break;
+ case 0x1B:
+ position.set("gsmModule", BufferUtil.readString(buf, length));
+ break;
+ case 0x1D:
+ position.set("agpsUpdate", buf.readUnsignedByte());
+ position.set("agpsLatitude", buf.readIntLE() * 0.0000001);
+ position.set("agpsLongitude", buf.readIntLE() * 0.0000001);
+ break;
+ case 0x30:
+ position.set("numberFlag", buf.readUnsignedByte());
+ position.set("number", BufferUtil.readString(buf, length - 1));
+ break;
+ case 0x31:
+ position.set("prefixFlag", buf.readUnsignedByte());
+ position.set("prefix", BufferUtil.readString(buf, length - 1));
+ break;
+ case 0x33:
+ position.set("phoneSwitches", buf.readUnsignedByte());
+ break;
+ case 0x40:
+ position.set("apn", BufferUtil.readString(buf, length));
+ break;
+ case 0x41:
+ position.set("apnUser", BufferUtil.readString(buf, length));
+ break;
+ case 0x42:
+ position.set("apnPassword", BufferUtil.readString(buf, length));
+ break;
+ case 0x43:
+ buf.readUnsignedByte(); // flag
+ position.set("port", buf.readUnsignedShort());
+ position.set("server", BufferUtil.readString(buf, length - 3));
+ break;
+ case 0x44:
+ position.set("heartbeatInterval", buf.readUnsignedInt());
+ position.set("uploadInterval", buf.readUnsignedInt());
+ position.set("uploadLazyInterval", buf.readUnsignedInt());
+ break;
+ case 0x47:
+ position.set("deviceId", BufferUtil.readString(buf, length));
+ break;
+ case 0x4E:
+ position.set("gsmBand", buf.readUnsignedByte());
+ break;
+ case 0x50:
+ position.set("powerAlert", buf.readUnsignedInt());
+ break;
+ case 0x51:
+ position.set("geoAlert", buf.readUnsignedInt());
+ break;
+ case 0x53:
+ position.set("motionAlert", buf.readUnsignedInt());
+ break;
+ case 0x5C:
+ position.set("barkLevel", buf.readUnsignedByte());
+ position.set("barkInterval", buf.readUnsignedInt());
+ break;
+ case 0x61:
+ position.set("msisdn", BufferUtil.readString(buf, length));
+ break;
+ case 0x62:
+ position.set("wifiWhitelist", buf.readUnsignedByte());
+ position.set("wifiWhitelistMac", ByteBufUtil.hexDump(buf.readSlice(6)));
+ break;
+ case 0x64:
+ position.set(Position.KEY_RSSI, buf.readUnsignedByte());
+ position.set("networkBand", buf.readUnsignedInt());
+ position.set(Position.KEY_OPERATOR, BufferUtil.readString(buf, length - 5));
+ break;
+ case 0x65:
+ position.set(Position.KEY_RSSI, buf.readUnsignedByte());
+ position.set("networkStatus", buf.readUnsignedByte());
+ position.set("serverStatus", buf.readUnsignedByte());
+ position.set("networkPlmn", ByteBufUtil.hexDump(buf.readSlice(6)));
+ position.set("homePlmn", ByteBufUtil.hexDump(buf.readSlice(6)));
+ break;
+ case 0x66:
+ position.set("imsi", BufferUtil.readString(buf, length));
+ break;
+ case 0x75:
+ position.set("extraEnableControl", buf.readUnsignedInt());
+ break;
+ default:
+ break;
+ }
+
+ buf.readerIndex(endIndex);
+ }
+
+ return position;
+ }
+
}
diff --git a/src/main/java/org/traccar/protocol/Minifinder2ProtocolEncoder.java b/src/main/java/org/traccar/protocol/Minifinder2ProtocolEncoder.java
new file mode 100644
index 000000000..6e330a4dd
--- /dev/null
+++ b/src/main/java/org/traccar/protocol/Minifinder2ProtocolEncoder.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2023 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.buffer.Unpooled;
+import org.traccar.BaseProtocolEncoder;
+import org.traccar.Protocol;
+import org.traccar.helper.Checksum;
+import org.traccar.model.Command;
+
+import java.nio.charset.StandardCharsets;
+
+public class Minifinder2ProtocolEncoder extends BaseProtocolEncoder {
+
+ public Minifinder2ProtocolEncoder(Protocol protocol) {
+ super(protocol);
+ }
+
+ private ByteBuf encodeContent(ByteBuf content) {
+
+ ByteBuf buf = Unpooled.buffer();
+
+ buf.writeByte(0xAB); // header
+ buf.writeByte(0x00); // properties
+ buf.writeShortLE(content.readableBytes());
+ buf.writeShortLE(Checksum.crc16(Checksum.CRC16_XMODEM, content.nioBuffer()));
+ buf.writeShortLE(1); // index
+ buf.writeBytes(content);
+
+ return buf;
+ }
+
+ @Override
+ protected Object encodeCommand(Command command) {
+
+ if (command.getType().equals(Command.TYPE_CONFIGURATION)) {
+ ByteBuf content = Unpooled.buffer();
+ content.writeByte(Minifinder2ProtocolDecoder.MSG_CONFIGURATION);
+ content.writeByte(1); // length
+ content.writeByte(0xF0); // type
+ }
+
+ if ("Nano".equalsIgnoreCase(getDeviceModel(command.getDeviceId()))) {
+ ByteBuf content = Unpooled.buffer();
+ if (command.getType().equals(Command.TYPE_FIRMWARE_UPDATE)) {
+ String url = command.getString(Command.KEY_DATA);
+ content.writeByte(Minifinder2ProtocolDecoder.MSG_SYSTEM_CONTROL);
+ content.writeByte(1 + url.length());
+ content.writeByte(0x30); // type
+ content.writeCharSequence(url, StandardCharsets.US_ASCII);
+ return encodeContent(content);
+ }
+ }
+
+ return null;
+ }
+
+}
diff --git a/src/main/java/org/traccar/protocol/MobilogixProtocol.java b/src/main/java/org/traccar/protocol/MobilogixProtocol.java
index 1b06c2249..36d6b5ed2 100644
--- a/src/main/java/org/traccar/protocol/MobilogixProtocol.java
+++ b/src/main/java/org/traccar/protocol/MobilogixProtocol.java
@@ -23,7 +23,7 @@ import org.traccar.PipelineBuilder;
import org.traccar.TrackerServer;
import org.traccar.config.Config;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class MobilogixProtocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/MoovboxProtocol.java b/src/main/java/org/traccar/protocol/MoovboxProtocol.java
index 16438e122..af853fe67 100644
--- a/src/main/java/org/traccar/protocol/MoovboxProtocol.java
+++ b/src/main/java/org/traccar/protocol/MoovboxProtocol.java
@@ -23,7 +23,7 @@ import org.traccar.PipelineBuilder;
import org.traccar.TrackerServer;
import org.traccar.config.Config;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class MoovboxProtocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/MotorProtocol.java b/src/main/java/org/traccar/protocol/MotorProtocol.java
index 3101c9b75..f17886577 100644
--- a/src/main/java/org/traccar/protocol/MotorProtocol.java
+++ b/src/main/java/org/traccar/protocol/MotorProtocol.java
@@ -22,7 +22,7 @@ import org.traccar.PipelineBuilder;
import org.traccar.TrackerServer;
import org.traccar.config.Config;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class MotorProtocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/Mta6Protocol.java b/src/main/java/org/traccar/protocol/Mta6Protocol.java
index 019fe4fa9..c1c6eb829 100644
--- a/src/main/java/org/traccar/protocol/Mta6Protocol.java
+++ b/src/main/java/org/traccar/protocol/Mta6Protocol.java
@@ -24,7 +24,7 @@ import org.traccar.TrackerServer;
import org.traccar.config.Config;
import org.traccar.config.Keys;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class Mta6Protocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/Mta6ProtocolDecoder.java b/src/main/java/org/traccar/protocol/Mta6ProtocolDecoder.java
index 896c7a2d2..9704cf099 100644
--- a/src/main/java/org/traccar/protocol/Mta6ProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/Mta6ProtocolDecoder.java
@@ -96,7 +96,7 @@ public class Mta6ProtocolDecoder extends BaseProtocolDecoder {
}
- private static class TimeReader extends FloatReader {
+ private static final class TimeReader extends FloatReader {
private long weekNumber;
diff --git a/src/main/java/org/traccar/protocol/MtxProtocol.java b/src/main/java/org/traccar/protocol/MtxProtocol.java
index e085b6221..12d324019 100644
--- a/src/main/java/org/traccar/protocol/MtxProtocol.java
+++ b/src/main/java/org/traccar/protocol/MtxProtocol.java
@@ -23,7 +23,7 @@ import org.traccar.PipelineBuilder;
import org.traccar.TrackerServer;
import org.traccar.config.Config;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class MtxProtocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/MxtProtocol.java b/src/main/java/org/traccar/protocol/MxtProtocol.java
index 1190bf527..2f0cc1658 100644
--- a/src/main/java/org/traccar/protocol/MxtProtocol.java
+++ b/src/main/java/org/traccar/protocol/MxtProtocol.java
@@ -20,7 +20,7 @@ import org.traccar.PipelineBuilder;
import org.traccar.TrackerServer;
import org.traccar.config.Config;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class MxtProtocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/NavigilProtocol.java b/src/main/java/org/traccar/protocol/NavigilProtocol.java
index 46a6c33a5..a309235c5 100644
--- a/src/main/java/org/traccar/protocol/NavigilProtocol.java
+++ b/src/main/java/org/traccar/protocol/NavigilProtocol.java
@@ -20,7 +20,7 @@ import org.traccar.PipelineBuilder;
import org.traccar.TrackerServer;
import org.traccar.config.Config;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class NavigilProtocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/NavisProtocol.java b/src/main/java/org/traccar/protocol/NavisProtocol.java
index 640a77803..96b5b0de0 100644
--- a/src/main/java/org/traccar/protocol/NavisProtocol.java
+++ b/src/main/java/org/traccar/protocol/NavisProtocol.java
@@ -20,7 +20,7 @@ import org.traccar.PipelineBuilder;
import org.traccar.TrackerServer;
import org.traccar.config.Config;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class NavisProtocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/NavisetProtocol.java b/src/main/java/org/traccar/protocol/NavisetProtocol.java
index 388f141f8..6df0b0436 100644
--- a/src/main/java/org/traccar/protocol/NavisetProtocol.java
+++ b/src/main/java/org/traccar/protocol/NavisetProtocol.java
@@ -20,7 +20,7 @@ import org.traccar.PipelineBuilder;
import org.traccar.TrackerServer;
import org.traccar.config.Config;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class NavisetProtocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/NavtelecomProtocol.java b/src/main/java/org/traccar/protocol/NavtelecomProtocol.java
index 50013d1a4..de5f93df1 100644
--- a/src/main/java/org/traccar/protocol/NavtelecomProtocol.java
+++ b/src/main/java/org/traccar/protocol/NavtelecomProtocol.java
@@ -20,7 +20,7 @@ import org.traccar.PipelineBuilder;
import org.traccar.TrackerServer;
import org.traccar.config.Config;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class NavtelecomProtocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/NavtelecomProtocolDecoder.java b/src/main/java/org/traccar/protocol/NavtelecomProtocolDecoder.java
index 08b1a8d0f..cd7ffa0e1 100644
--- a/src/main/java/org/traccar/protocol/NavtelecomProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/NavtelecomProtocolDecoder.java
@@ -193,12 +193,12 @@ public class NavtelecomProtocolDecoder extends BaseProtocolDecoder {
Position position = new Position(getProtocolName());
position.setDeviceId(deviceSession.getDeviceId());
- for (int j = 0; j < bits.length(); j++) {
- if (bits.get(j)) {
+ for (int j = 1; j <= bits.length(); j++) {
+ if (bits.get(j - 1)) {
int value;
- switch (j + 1) {
+ switch (j) {
case 1:
position.set(Position.KEY_INDEX, buf.readUnsignedIntLE());
break;
@@ -208,6 +208,18 @@ public class NavtelecomProtocolDecoder extends BaseProtocolDecoder {
case 3:
position.setDeviceTime(new Date(buf.readUnsignedIntLE() * 1000));
break;
+ case 4:
+ value = buf.readUnsignedByte();
+ position.set(
+ Position.KEY_ALARM,
+ BitUtil.check(value, 2) ? Position.ALARM_GENERAL : null);
+ int guardMode = BitUtil.between(value, 3, 4);
+ position.set(Position.KEY_ARMED, (0 < guardMode) && (guardMode < 3));
+ break;
+ case 5:
+ value = buf.readUnsignedByte();
+ position.set(Position.KEY_ROAMING, BitUtil.check(value, 6) ? true : null);
+ break;
case 8:
value = buf.readUnsignedByte();
position.setValid(BitUtil.check(value, 1));
@@ -232,7 +244,7 @@ public class NavtelecomProtocolDecoder extends BaseProtocolDecoder {
position.setCourse(buf.readUnsignedShortLE());
break;
case 15:
- position.set(Position.KEY_ODOMETER, buf.readFloatLE());
+ position.set(Position.KEY_ODOMETER, buf.readFloatLE() * 1000);
break;
case 19:
position.set(Position.KEY_POWER, buf.readShortLE() * 0.001);
@@ -246,7 +258,7 @@ public class NavtelecomProtocolDecoder extends BaseProtocolDecoder {
case 24:
case 25:
case 26:
- position.set(Position.PREFIX_ADC + (j + 2 - 21), buf.readUnsignedShortLE() * 0.001);
+ position.set(Position.PREFIX_ADC + (j + 1 - 21), buf.readUnsignedShortLE() * 0.001);
break;
case 29:
value = buf.readUnsignedByte();
@@ -262,14 +274,14 @@ public class NavtelecomProtocolDecoder extends BaseProtocolDecoder {
break;
case 33:
case 34:
- position.set(Position.PREFIX_COUNT + (j + 2 - 33), buf.readUnsignedIntLE());
+ position.set(Position.PREFIX_COUNT + (j + 1 - 33), buf.readUnsignedIntLE());
break;
case 35:
case 36:
- position.set("freq" + (j + 2 - 35), buf.readUnsignedShortLE());
+ position.set("freq" + (j + 1 - 35), buf.readUnsignedShortLE());
break;
case 37:
- position.set(Position.KEY_HOURS, buf.readUnsignedIntLE());
+ position.set(Position.KEY_HOURS, buf.readUnsignedIntLE() * 1000);
break;
case 38:
case 39:
@@ -278,7 +290,8 @@ public class NavtelecomProtocolDecoder extends BaseProtocolDecoder {
case 42:
case 43:
value = buf.readUnsignedShortLE();
- position.set("fuel" + (j + 2 - 38), (value < 65500) ? value : null);
+ position.set(
+ Position.KEY_FUEL_LEVEL + (j + 1 - 38), (value < 65500) ? value : null);
break;
case 44:
value = buf.readUnsignedShortLE();
@@ -294,8 +307,75 @@ public class NavtelecomProtocolDecoder extends BaseProtocolDecoder {
case 52:
value = buf.readByte();
position.set(
- Position.PREFIX_TEMP + (j + 2 - 45),
- (value != (byte) 0x80) ? value : null);
+ Position.PREFIX_TEMP + (j + 1 - 45), (value != (byte) 0x80) ? value : null);
+ break;
+ case 53:
+ value = buf.readUnsignedShortLE();
+ if (value != 0x7FFF) {
+ if (BitUtil.check(value, 15)) {
+ position.set("obdFuelLevel", BitUtil.to(value, 14));
+ } else {
+ position.set("obdFuel", BitUtil.to(value, 14) * 0.1);
+ }
+ }
+ break;
+ case 54:
+ double fuelUsed = buf.readFloatLE() * 0.5;
+ position.set(Position.KEY_FUEL_USED, (fuelUsed >= 0) ? fuelUsed : null);
+ break;
+ case 55:
+ value = buf.readUnsignedShortLE();
+ position.set(Position.KEY_RPM, (value != 0xFFFF) ? value : null);
+ break;
+ case 56:
+ value = buf.readByte();
+ position.set(Position.KEY_COOLANT_TEMP, (value != (byte) 0x80) ? value : null);
+ break;
+ case 57:
+ position.set(Position.KEY_OBD_ODOMETER, buf.readFloatLE() * 1000);
+ break;
+ case 58:
+ case 59:
+ case 60:
+ case 61:
+ case 62:
+ value = buf.readUnsignedShortLE();
+ position.set("axleWeight" + (j + 1 - 58), (value != 0xFFFF) ? value : null);
+ break;
+ case 63:
+ value = buf.readUnsignedByte();
+ position.set("acceleratorPosition", (value != 0xFF) ? value : null);
+ break;
+ case 64:
+ value = buf.readUnsignedByte();
+ position.set("brakePosition", (value != 0xFF) ? value : null);
+ break;
+ case 65:
+ value = buf.readUnsignedByte();
+ position.set(Position.KEY_ENGINE_LOAD, (value != 0xFF) ? value : null);
+ break;
+ case 66:
+ value = buf.readUnsignedShortLE();
+ if (value != 0x7FFF) {
+ if (BitUtil.check(value, 15)) {
+ position.set("obdAdBlueLevel", BitUtil.to(value, 14));
+ } else {
+ position.set("obdAdBlue", BitUtil.to(value, 14) * 0.1);
+ }
+ }
+ break;
+ case 67:
+ position.set("obdHours", buf.readUnsignedIntLE() * 1000);
+ break;
+ case 68:
+ value = buf.readUnsignedShortLE();
+ position.set(
+ Position.KEY_ODOMETER_SERVICE,
+ (value != 0xFFFF) ? (value * 5000) : null);
+ break;
+ case 69:
+ value = buf.readUnsignedByte();
+ position.set(Position.KEY_OBD_SPEED, (value != 0xFF) ? value : null);
break;
case 78:
case 79:
@@ -303,10 +383,39 @@ public class NavtelecomProtocolDecoder extends BaseProtocolDecoder {
case 81:
case 82:
case 83:
- position.set("fuelTemp" + (j + 2 - 78), (int) buf.readByte());
+ position.set("fuelTemp" + (j + 1 - 78), (int) buf.readByte());
+ break;
+ case 163:
+ case 164:
+ case 165:
+ case 166:
+ value = buf.readShortLE();
+ position.set(
+ Position.PREFIX_TEMP + (j + 1 + 8 - 163),
+ (value != (short) 0x8000) ? value * 0.05 : null);
+ break;
+ case 167:
+ case 168:
+ case 169:
+ case 170:
+ value = buf.readUnsignedByte();
+ position.set("humidity" + (j + 1 - 167), (value != 0xFF) ? value * 0.5 : null);
+ break;
+ case 206:
+ position.set("diagnostic", buf.readUnsignedIntLE());
break;
default:
- buf.skipBytes(getItemLength(j + 1));
+ if ((207 <= j) && (j <= 222)) {
+ position.set("user1Byte" + (j + 1 - 207), buf.readUnsignedByte());
+ } else if ((223 <= j) && (j <= 237)) {
+ position.set("user2Byte" + (j + 1 - 223), buf.readUnsignedShortLE());
+ } else if ((238 <= j) && (j <= 252)) {
+ position.set("user4Byte" + (j + 1 - 238), buf.readUnsignedIntLE());
+ } else if ((253 <= j) && (j <= 255)) {
+ position.set("user8Byte" + (j + 1 - 253), buf.readLongLE());
+ } else {
+ buf.skipBytes(getItemLength(j));
+ }
break;
}
}
diff --git a/src/main/java/org/traccar/protocol/NdtpV6Protocol.java b/src/main/java/org/traccar/protocol/NdtpV6Protocol.java
index ce0dbbef2..9493132f5 100644
--- a/src/main/java/org/traccar/protocol/NdtpV6Protocol.java
+++ b/src/main/java/org/traccar/protocol/NdtpV6Protocol.java
@@ -21,7 +21,7 @@ import org.traccar.PipelineBuilder;
import org.traccar.TrackerServer;
import org.traccar.config.Config;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class NdtpV6Protocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/NeosProtocol.java b/src/main/java/org/traccar/protocol/NeosProtocol.java
index 0787b6562..16a6ba5a0 100644
--- a/src/main/java/org/traccar/protocol/NeosProtocol.java
+++ b/src/main/java/org/traccar/protocol/NeosProtocol.java
@@ -22,7 +22,7 @@ import org.traccar.PipelineBuilder;
import org.traccar.TrackerServer;
import org.traccar.config.Config;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class NeosProtocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/NetProtocol.java b/src/main/java/org/traccar/protocol/NetProtocol.java
index f27e4afb8..e011660da 100644
--- a/src/main/java/org/traccar/protocol/NetProtocol.java
+++ b/src/main/java/org/traccar/protocol/NetProtocol.java
@@ -23,7 +23,7 @@ import org.traccar.PipelineBuilder;
import org.traccar.TrackerServer;
import org.traccar.config.Config;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class NetProtocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/NiotProtocol.java b/src/main/java/org/traccar/protocol/NiotProtocol.java
index 0fbe0c689..7eacd5ff3 100644
--- a/src/main/java/org/traccar/protocol/NiotProtocol.java
+++ b/src/main/java/org/traccar/protocol/NiotProtocol.java
@@ -21,7 +21,7 @@ import org.traccar.PipelineBuilder;
import org.traccar.TrackerServer;
import org.traccar.config.Config;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class NiotProtocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/NoranProtocol.java b/src/main/java/org/traccar/protocol/NoranProtocol.java
index 626991029..d03e52be5 100644
--- a/src/main/java/org/traccar/protocol/NoranProtocol.java
+++ b/src/main/java/org/traccar/protocol/NoranProtocol.java
@@ -21,7 +21,7 @@ import org.traccar.TrackerServer;
import org.traccar.config.Config;
import org.traccar.model.Command;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class NoranProtocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/NtoProtocol.java b/src/main/java/org/traccar/protocol/NtoProtocol.java
new file mode 100644
index 000000000..d3596e287
--- /dev/null
+++ b/src/main/java/org/traccar/protocol/NtoProtocol.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2023 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 jakarta.inject.Inject;
+import org.traccar.BaseProtocol;
+import org.traccar.CharacterDelimiterFrameDecoder;
+import org.traccar.PipelineBuilder;
+import org.traccar.TrackerServer;
+import org.traccar.config.Config;
+
+public class NtoProtocol extends BaseProtocol {
+
+ @Inject
+ public NtoProtocol(Config config) {
+ addServer(new TrackerServer(config, getName(), false) {
+ @Override
+ protected void addProtocolHandlers(PipelineBuilder pipeline, Config config) {
+ pipeline.addLast(new CharacterDelimiterFrameDecoder(1024, '&'));
+ pipeline.addLast(new StringEncoder());
+ pipeline.addLast(new StringDecoder());
+ pipeline.addLast(new NtoProtocolDecoder(NtoProtocol.this));
+ }
+ });
+ }
+
+}
diff --git a/src/main/java/org/traccar/protocol/NtoProtocolDecoder.java b/src/main/java/org/traccar/protocol/NtoProtocolDecoder.java
new file mode 100644
index 000000000..ba9ebd95d
--- /dev/null
+++ b/src/main/java/org/traccar/protocol/NtoProtocolDecoder.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright 2023 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.Protocol;
+import org.traccar.helper.BitUtil;
+import org.traccar.helper.Parser;
+import org.traccar.helper.PatternBuilder;
+import org.traccar.model.Position;
+import org.traccar.session.DeviceSession;
+
+import java.net.SocketAddress;
+import java.util.regex.Pattern;
+
+public class NtoProtocolDecoder extends BaseProtocolDecoder {
+
+ public NtoProtocolDecoder(Protocol protocol) {
+ super(protocol);
+ }
+
+ private static final Pattern PATTERN = new PatternBuilder()
+ .text("^NB,") // manufacturer
+ .number("(d+),") // imei
+ .expression("(...),") // type
+ .number("(dd)(dd)(dd),") // date (ddmmyy)
+ .number("(dd)(dd)(dd),") // time (hhmmss)
+ .expression("([AVM]),") // validity
+ .number("([NS]),(dd)(dd.d+),") // latitude
+ .number("([EW]),(ddd)(dd.d+),") // longitude
+ .number("(d+.?d*),") // speed
+ .number("(d+),") // course
+ .number("(x+),") // status
+ .any()
+ .compile();
+
+ @Override
+ protected Object decode(
+ Channel channel, SocketAddress remoteAddress, Object msg) throws Exception {
+
+ Parser parser = new Parser(PATTERN, (String) msg);
+ if (!parser.matches()) {
+ return null;
+ }
+
+ DeviceSession deviceSession = getDeviceSession(channel, remoteAddress, parser.next());
+ if (deviceSession == null) {
+ return null;
+ }
+
+ Position position = new Position(getProtocolName());
+ position.setDeviceId(deviceSession.getDeviceId());
+
+ position.set(Position.KEY_TYPE, parser.next());
+
+ position.setTime(parser.nextDateTime(Parser.DateTimeFormat.DMY_HMS));
+
+ position.setValid(parser.next().equals("A"));
+ position.setLatitude(parser.nextCoordinate(Parser.CoordinateFormat.HEM_DEG_MIN));
+ position.setLongitude(parser.nextCoordinate(Parser.CoordinateFormat.HEM_DEG_MIN));
+ position.setSpeed(parser.nextDouble());
+ position.setCourse(parser.nextInt());
+
+ long status = parser.nextHexLong();
+ position.set(Position.KEY_STATUS, status);
+ position.set(Position.KEY_ALARM, BitUtil.check(status, 1) ? Position.ALARM_JAMMING : null);
+ position.set(Position.KEY_ALARM, BitUtil.check(status, 3 * 8 + 1) ? Position.ALARM_POWER_CUT : null);
+ position.set(Position.KEY_ALARM, BitUtil.check(status, 3 * 8 + 2) ? Position.ALARM_OVERSPEED : null);
+ position.set(Position.KEY_ALARM, BitUtil.check(status, 3 * 8 + 3) ? Position.ALARM_VIBRATION : null);
+ position.set(Position.KEY_ALARM, BitUtil.check(status, 3 * 8 + 4) ? Position.ALARM_GEOFENCE_ENTER : null);
+ position.set(Position.KEY_ALARM, BitUtil.check(status, 3 * 8 + 5) ? Position.ALARM_GEOFENCE_EXIT : null);
+ position.set(Position.KEY_ALARM, BitUtil.check(status, 4 * 8) ? Position.ALARM_LOW_BATTERY : null);
+ position.set(Position.KEY_ALARM, BitUtil.check(status, 4 * 8 + 4) ? Position.ALARM_DOOR : null);
+
+ return position;
+ }
+
+}
diff --git a/src/main/java/org/traccar/protocol/NvsProtocol.java b/src/main/java/org/traccar/protocol/NvsProtocol.java
index 7ed488e38..8a4ece30d 100644
--- a/src/main/java/org/traccar/protocol/NvsProtocol.java
+++ b/src/main/java/org/traccar/protocol/NvsProtocol.java
@@ -20,7 +20,7 @@ import org.traccar.PipelineBuilder;
import org.traccar.TrackerServer;
import org.traccar.config.Config;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class NvsProtocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/NyitechProtocol.java b/src/main/java/org/traccar/protocol/NyitechProtocol.java
index e7ef10945..225b1bd5a 100644
--- a/src/main/java/org/traccar/protocol/NyitechProtocol.java
+++ b/src/main/java/org/traccar/protocol/NyitechProtocol.java
@@ -23,7 +23,7 @@ import org.traccar.config.Config;
import java.nio.ByteOrder;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class NyitechProtocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/ObdDongleProtocol.java b/src/main/java/org/traccar/protocol/ObdDongleProtocol.java
index 94f450426..9fcc35d0d 100644
--- a/src/main/java/org/traccar/protocol/ObdDongleProtocol.java
+++ b/src/main/java/org/traccar/protocol/ObdDongleProtocol.java
@@ -21,7 +21,7 @@ import org.traccar.PipelineBuilder;
import org.traccar.TrackerServer;
import org.traccar.config.Config;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class ObdDongleProtocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/OigoProtocol.java b/src/main/java/org/traccar/protocol/OigoProtocol.java
index 0539bada6..3483f8270 100644
--- a/src/main/java/org/traccar/protocol/OigoProtocol.java
+++ b/src/main/java/org/traccar/protocol/OigoProtocol.java
@@ -20,7 +20,7 @@ import org.traccar.PipelineBuilder;
import org.traccar.TrackerServer;
import org.traccar.config.Config;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class OigoProtocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/OkoProtocol.java b/src/main/java/org/traccar/protocol/OkoProtocol.java
index 29c8bc1b9..6ca6c0e93 100644
--- a/src/main/java/org/traccar/protocol/OkoProtocol.java
+++ b/src/main/java/org/traccar/protocol/OkoProtocol.java
@@ -22,7 +22,7 @@ import org.traccar.PipelineBuilder;
import org.traccar.TrackerServer;
import org.traccar.config.Config;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class OkoProtocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/OmnicommProtocol.java b/src/main/java/org/traccar/protocol/OmnicommProtocol.java
index dd400c779..b59b84132 100644
--- a/src/main/java/org/traccar/protocol/OmnicommProtocol.java
+++ b/src/main/java/org/traccar/protocol/OmnicommProtocol.java
@@ -20,7 +20,7 @@ import org.traccar.PipelineBuilder;
import org.traccar.TrackerServer;
import org.traccar.config.Config;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class OmnicommProtocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/OpenGtsProtocol.java b/src/main/java/org/traccar/protocol/OpenGtsProtocol.java
index 5443b4ffc..24d6de706 100644
--- a/src/main/java/org/traccar/protocol/OpenGtsProtocol.java
+++ b/src/main/java/org/traccar/protocol/OpenGtsProtocol.java
@@ -23,7 +23,7 @@ import org.traccar.PipelineBuilder;
import org.traccar.TrackerServer;
import org.traccar.config.Config;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class OpenGtsProtocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/OrbcommProtocol.java b/src/main/java/org/traccar/protocol/OrbcommProtocol.java
index fb09f0abb..06b00619c 100644
--- a/src/main/java/org/traccar/protocol/OrbcommProtocol.java
+++ b/src/main/java/org/traccar/protocol/OrbcommProtocol.java
@@ -23,7 +23,7 @@ import org.traccar.PipelineBuilder;
import org.traccar.TrackerClient;
import org.traccar.config.Config;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class OrbcommProtocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/OrbcommProtocolDecoder.java b/src/main/java/org/traccar/protocol/OrbcommProtocolDecoder.java
index 1164d72a1..7ed13d647 100644
--- a/src/main/java/org/traccar/protocol/OrbcommProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/OrbcommProtocolDecoder.java
@@ -24,10 +24,10 @@ import org.traccar.Protocol;
import org.traccar.helper.UnitsConverter;
import org.traccar.model.Position;
-import javax.json.Json;
-import javax.json.JsonArray;
-import javax.json.JsonObject;
-import javax.json.JsonValue;
+import jakarta.json.Json;
+import jakarta.json.JsonArray;
+import jakarta.json.JsonObject;
+import jakarta.json.JsonValue;
import java.io.StringReader;
import java.net.SocketAddress;
import java.nio.charset.StandardCharsets;
diff --git a/src/main/java/org/traccar/protocol/OrionProtocol.java b/src/main/java/org/traccar/protocol/OrionProtocol.java
index 2dec7cd06..b78af462b 100644
--- a/src/main/java/org/traccar/protocol/OrionProtocol.java
+++ b/src/main/java/org/traccar/protocol/OrionProtocol.java
@@ -20,7 +20,7 @@ import org.traccar.PipelineBuilder;
import org.traccar.TrackerServer;
import org.traccar.config.Config;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class OrionProtocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/OsmAndProtocol.java b/src/main/java/org/traccar/protocol/OsmAndProtocol.java
index a86bc70d7..e06580949 100644
--- a/src/main/java/org/traccar/protocol/OsmAndProtocol.java
+++ b/src/main/java/org/traccar/protocol/OsmAndProtocol.java
@@ -23,7 +23,7 @@ import org.traccar.PipelineBuilder;
import org.traccar.TrackerServer;
import org.traccar.config.Config;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class OsmAndProtocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/OutsafeProtocol.java b/src/main/java/org/traccar/protocol/OutsafeProtocol.java
index 0099be456..159534883 100644
--- a/src/main/java/org/traccar/protocol/OutsafeProtocol.java
+++ b/src/main/java/org/traccar/protocol/OutsafeProtocol.java
@@ -23,7 +23,7 @@ import org.traccar.PipelineBuilder;
import org.traccar.TrackerServer;
import org.traccar.config.Config;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class OutsafeProtocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/OutsafeProtocolDecoder.java b/src/main/java/org/traccar/protocol/OutsafeProtocolDecoder.java
index 62b873be7..f71778412 100644
--- a/src/main/java/org/traccar/protocol/OutsafeProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/OutsafeProtocolDecoder.java
@@ -23,11 +23,11 @@ import org.traccar.session.DeviceSession;
import org.traccar.Protocol;
import org.traccar.model.Position;
-import javax.json.Json;
-import javax.json.JsonNumber;
-import javax.json.JsonObject;
-import javax.json.JsonString;
-import javax.json.JsonValue;
+import jakarta.json.Json;
+import jakarta.json.JsonNumber;
+import jakarta.json.JsonObject;
+import jakarta.json.JsonString;
+import jakarta.json.JsonValue;
import java.io.StringReader;
import java.net.SocketAddress;
import java.nio.charset.StandardCharsets;
diff --git a/src/main/java/org/traccar/protocol/OwnTracksProtocol.java b/src/main/java/org/traccar/protocol/OwnTracksProtocol.java
index 9ad337f19..c509ad282 100644
--- a/src/main/java/org/traccar/protocol/OwnTracksProtocol.java
+++ b/src/main/java/org/traccar/protocol/OwnTracksProtocol.java
@@ -24,7 +24,7 @@ import org.traccar.PipelineBuilder;
import org.traccar.TrackerServer;
import org.traccar.config.Config;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class OwnTracksProtocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/OwnTracksProtocolDecoder.java b/src/main/java/org/traccar/protocol/OwnTracksProtocolDecoder.java
index 71ac87168..e54d07fa7 100644
--- a/src/main/java/org/traccar/protocol/OwnTracksProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/OwnTracksProtocolDecoder.java
@@ -25,8 +25,8 @@ import org.traccar.Protocol;
import org.traccar.helper.UnitsConverter;
import org.traccar.model.Position;
-import javax.json.Json;
-import javax.json.JsonObject;
+import jakarta.json.Json;
+import jakarta.json.JsonObject;
import java.io.StringReader;
import java.net.SocketAddress;
import java.nio.charset.StandardCharsets;
diff --git a/src/main/java/org/traccar/protocol/PacificTrackProtocol.java b/src/main/java/org/traccar/protocol/PacificTrackProtocol.java
index 709729ef1..a315d4d9f 100644
--- a/src/main/java/org/traccar/protocol/PacificTrackProtocol.java
+++ b/src/main/java/org/traccar/protocol/PacificTrackProtocol.java
@@ -20,7 +20,7 @@ import org.traccar.PipelineBuilder;
import org.traccar.TrackerServer;
import org.traccar.config.Config;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class PacificTrackProtocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/PathAwayProtocol.java b/src/main/java/org/traccar/protocol/PathAwayProtocol.java
index 1d13eea95..a65740475 100644
--- a/src/main/java/org/traccar/protocol/PathAwayProtocol.java
+++ b/src/main/java/org/traccar/protocol/PathAwayProtocol.java
@@ -23,7 +23,7 @@ import org.traccar.PipelineBuilder;
import org.traccar.TrackerServer;
import org.traccar.config.Config;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class PathAwayProtocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/PiligrimProtocol.java b/src/main/java/org/traccar/protocol/PiligrimProtocol.java
index aa45a0def..9dd1bc491 100644
--- a/src/main/java/org/traccar/protocol/PiligrimProtocol.java
+++ b/src/main/java/org/traccar/protocol/PiligrimProtocol.java
@@ -23,7 +23,7 @@ import org.traccar.PipelineBuilder;
import org.traccar.TrackerServer;
import org.traccar.config.Config;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class PiligrimProtocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/PluginProtocol.java b/src/main/java/org/traccar/protocol/PluginProtocol.java
index b2101b18d..fff1830e8 100644
--- a/src/main/java/org/traccar/protocol/PluginProtocol.java
+++ b/src/main/java/org/traccar/protocol/PluginProtocol.java
@@ -23,7 +23,7 @@ import org.traccar.PipelineBuilder;
import org.traccar.TrackerServer;
import org.traccar.config.Config;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class PluginProtocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/PolteProtocol.java b/src/main/java/org/traccar/protocol/PolteProtocol.java
index 69666cc0e..0fbedfb09 100644
--- a/src/main/java/org/traccar/protocol/PolteProtocol.java
+++ b/src/main/java/org/traccar/protocol/PolteProtocol.java
@@ -23,7 +23,7 @@ import org.traccar.PipelineBuilder;
import org.traccar.TrackerServer;
import org.traccar.config.Config;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class PolteProtocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/PolteProtocolDecoder.java b/src/main/java/org/traccar/protocol/PolteProtocolDecoder.java
index 028de5424..8954db491 100644
--- a/src/main/java/org/traccar/protocol/PolteProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/PolteProtocolDecoder.java
@@ -23,8 +23,8 @@ import org.traccar.session.DeviceSession;
import org.traccar.Protocol;
import org.traccar.model.Position;
-import javax.json.Json;
-import javax.json.JsonObject;
+import jakarta.json.Json;
+import jakarta.json.JsonObject;
import java.io.StringReader;
import java.net.SocketAddress;
import java.nio.charset.StandardCharsets;
diff --git a/src/main/java/org/traccar/protocol/PortmanProtocol.java b/src/main/java/org/traccar/protocol/PortmanProtocol.java
index de78013fa..3a4b49289 100644
--- a/src/main/java/org/traccar/protocol/PortmanProtocol.java
+++ b/src/main/java/org/traccar/protocol/PortmanProtocol.java
@@ -24,7 +24,7 @@ import org.traccar.TrackerServer;
import org.traccar.config.Config;
import org.traccar.model.Command;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class PortmanProtocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/PortmanProtocolDecoder.java b/src/main/java/org/traccar/protocol/PortmanProtocolDecoder.java
index da9403313..716f2694b 100644
--- a/src/main/java/org/traccar/protocol/PortmanProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/PortmanProtocolDecoder.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2020 - 2021 Anton Tananaev (anton@traccar.org)
+ * Copyright 2020 - 2023 Anton Tananaev (anton@traccar.org)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -34,7 +34,11 @@ public class PortmanProtocolDecoder extends BaseProtocolDecoder {
}
private static final Pattern PATTERN_STANDARD = new PatternBuilder()
+ .groupBegin()
.text("$PTMLA,") // header
+ .or()
+ .text("%%") // header
+ .groupEnd()
.expression("([^,]+),") // id
.expression("([ABCL]),") // validity
.number("(dd)(dd)(dd)") // date (yymmdd)
@@ -47,12 +51,19 @@ public class PortmanProtocolDecoder extends BaseProtocolDecoder {
.number("(d+),") // course
.number("(?:NA|C(-?d+)),") // temperature
.number("(x{8}),") // status
- .number("(?:NA|(d+)),") // card id
+ .groupBegin()
+ .text("NA")
+ .or()
+ .number("F(d+)") // fuel
+ .or()
+ .number("(d+)") // card id
+ .groupEnd(",")
.number("(d+),") // event
.number("(d+),") // satellites
.number("(d+.d+),") // odometer
- .number("(d+),") // rssi
- .number("(?:G(d+)|[^,]*)") // fuel
+ .number("(d+)") // rssi
+ .number(",G(d+)").optional() // fuel
+ .any()
.compile();
private Object decodeStandard(Channel channel, SocketAddress remoteAddress, String sentence) {
@@ -79,6 +90,9 @@ public class PortmanProtocolDecoder extends BaseProtocolDecoder {
position.set(Position.PREFIX_TEMP + 1, parser.next());
position.set(Position.KEY_STATUS, parser.nextHexLong());
+ if (parser.hasNext()) {
+ position.set(Position.KEY_FUEL_LEVEL, parser.nextInt() * 0.1);
+ }
position.set(Position.KEY_DRIVER_UNIQUE_ID, parser.next());
int event = parser.nextInt();
@@ -159,7 +173,7 @@ public class PortmanProtocolDecoder extends BaseProtocolDecoder {
Channel channel, SocketAddress remoteAddress, Object msg) throws Exception {
String sentence = (String) msg;
- if (sentence.startsWith("$PTMLA")) {
+ if (sentence.startsWith("%%") || sentence.startsWith("$PTMLA")) {
return decodeStandard(channel, remoteAddress, sentence);
} else if (sentence.startsWith("$EXT")) {
return decodeExtended(channel, remoteAddress, sentence);
diff --git a/src/main/java/org/traccar/protocol/PositrexProtocol.java b/src/main/java/org/traccar/protocol/PositrexProtocol.java
new file mode 100644
index 000000000..5cf389fbe
--- /dev/null
+++ b/src/main/java/org/traccar/protocol/PositrexProtocol.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2023 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 jakarta.inject.Inject;
+import org.traccar.BaseProtocol;
+import org.traccar.PipelineBuilder;
+import org.traccar.TrackerServer;
+import org.traccar.config.Config;
+
+public class PositrexProtocol extends BaseProtocol {
+
+ @Inject
+ public PositrexProtocol(Config config) {
+ addServer(new TrackerServer(config, getName(), true) {
+ @Override
+ protected void addProtocolHandlers(PipelineBuilder pipeline, Config config) {
+ pipeline.addLast(new PositrexProtocolDecoder(PositrexProtocol.this));
+ }
+ });
+ }
+
+}
diff --git a/src/main/java/org/traccar/protocol/PositrexProtocolDecoder.java b/src/main/java/org/traccar/protocol/PositrexProtocolDecoder.java
new file mode 100644
index 000000000..82ae2c134
--- /dev/null
+++ b/src/main/java/org/traccar/protocol/PositrexProtocolDecoder.java
@@ -0,0 +1,116 @@
+/*
+ * Copyright 2023 Anton Tananaev (anton@traccar.org)
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.traccar.protocol;
+
+import io.netty.buffer.ByteBuf;
+import io.netty.channel.Channel;
+import org.traccar.BaseProtocolDecoder;
+import org.traccar.Protocol;
+import org.traccar.helper.BitUtil;
+import org.traccar.helper.DateBuilder;
+import org.traccar.helper.UnitsConverter;
+import org.traccar.model.Position;
+import org.traccar.session.DeviceSession;
+
+import java.net.SocketAddress;
+import java.util.Date;
+
+public class PositrexProtocolDecoder extends BaseProtocolDecoder {
+
+ public PositrexProtocolDecoder(Protocol protocol) {
+ super(protocol);
+ }
+
+ public static final int MSG_PING = 0x2E;
+
+ private Date readTime(ByteBuf buf) {
+ long time = buf.readUnsignedInt();
+ DateBuilder dateBuilder = new DateBuilder();
+ dateBuilder.setSecond((int) (time % 60));
+ time /= 60;
+ dateBuilder.setMinute((int) (time % 60));
+ time /= 60;
+ dateBuilder.setHour((int) (time % 24));
+ time /= 24;
+ dateBuilder.setDay((int) (time % 32));
+ time /= 32;
+ dateBuilder.setMonth((int) (time % 13));
+ dateBuilder.setYear((int) (2000 + time / 13));
+ return dateBuilder.getDate();
+ }
+
+ @Override
+ protected Object decode(
+ Channel channel, SocketAddress remoteAddress, Object msg) throws Exception {
+
+ ByteBuf buf = (ByteBuf) msg;
+
+ int first = buf.getUnsignedByte(buf.readerIndex());
+ long deviceId;
+ if (BitUtil.check(first, 7)) {
+ if (BitUtil.check(first, 6)) {
+ deviceId = 73000000 + BitUtil.to(buf.readUnsignedInt(), 30);
+ } else if (!BitUtil.check(first, 5) && !BitUtil.check(first, 4)) {
+ deviceId = 7590000 + BitUtil.to(buf.readUnsignedMedium(), 20);
+ } else {
+ deviceId = 70000000 + BitUtil.to(buf.readUnsignedMedium(), 20);
+ }
+ } else {
+ deviceId = 7560000 + buf.readUnsignedShort();
+ }
+
+ DeviceSession deviceSession = getDeviceSession(channel, remoteAddress, String.valueOf(deviceId));
+ if (deviceSession == null) {
+ return null;
+ }
+
+ int service = buf.readUnsignedByte();
+ if (service == MSG_PING) {
+
+ Position position = new Position(getProtocolName());
+ position.setDeviceId(deviceSession.getDeviceId());
+
+ position.setTime(readTime(buf));
+
+ int latitude = buf.readMedium();
+ int longitude = buf.readMedium();
+
+ position.setValid(BitUtil.check(latitude, 23));
+ position.setLatitude(BitUtil.to(latitude, 23) * 0.000025);
+ position.setLongitude(longitude * 0.000025);
+
+ position.setSpeed(UnitsConverter.knotsFromKph(buf.readUnsignedByte()));
+ position.setCourse(buf.readUnsignedByte() * 2);
+
+ position.set(Position.PREFIX_IO, buf.readUnsignedByte());
+ position.set(Position.KEY_ODOMETER, buf.readUnsignedInt());
+ buf.readUnsignedInt(); // report begin
+ buf.readUnsignedInt(); // report end
+ buf.readUnsignedInt(); // number of records
+
+ if (buf.isReadable()) {
+ position.set(Position.KEY_POWER, buf.readUnsignedShort() * 0.01);
+ position.set(Position.KEY_BATTERY, buf.readUnsignedShort() * 0.01);
+ }
+
+ return position;
+
+ }
+
+ return null;
+ }
+
+}
diff --git a/src/main/java/org/traccar/protocol/PretraceProtocol.java b/src/main/java/org/traccar/protocol/PretraceProtocol.java
index b77dd97bf..54a34fc69 100644
--- a/src/main/java/org/traccar/protocol/PretraceProtocol.java
+++ b/src/main/java/org/traccar/protocol/PretraceProtocol.java
@@ -24,7 +24,7 @@ import org.traccar.TrackerServer;
import org.traccar.config.Config;
import org.traccar.model.Command;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class PretraceProtocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/PricolProtocol.java b/src/main/java/org/traccar/protocol/PricolProtocol.java
index f5e904541..7b0e7386c 100644
--- a/src/main/java/org/traccar/protocol/PricolProtocol.java
+++ b/src/main/java/org/traccar/protocol/PricolProtocol.java
@@ -21,7 +21,7 @@ import org.traccar.PipelineBuilder;
import org.traccar.TrackerServer;
import org.traccar.config.Config;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class PricolProtocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/ProgressProtocol.java b/src/main/java/org/traccar/protocol/ProgressProtocol.java
index 49eb6847f..8d159ef24 100644
--- a/src/main/java/org/traccar/protocol/ProgressProtocol.java
+++ b/src/main/java/org/traccar/protocol/ProgressProtocol.java
@@ -22,7 +22,7 @@ import org.traccar.TrackerServer;
import org.traccar.config.Config;
import java.nio.ByteOrder;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class ProgressProtocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/PstProtocol.java b/src/main/java/org/traccar/protocol/PstProtocol.java
index 73f978cbd..01a83b31f 100644
--- a/src/main/java/org/traccar/protocol/PstProtocol.java
+++ b/src/main/java/org/traccar/protocol/PstProtocol.java
@@ -21,7 +21,7 @@ import org.traccar.TrackerServer;
import org.traccar.config.Config;
import org.traccar.model.Command;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class PstProtocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/Pt215Protocol.java b/src/main/java/org/traccar/protocol/Pt215Protocol.java
index b272582a4..fd67b1241 100644
--- a/src/main/java/org/traccar/protocol/Pt215Protocol.java
+++ b/src/main/java/org/traccar/protocol/Pt215Protocol.java
@@ -21,7 +21,7 @@ import org.traccar.PipelineBuilder;
import org.traccar.TrackerServer;
import org.traccar.config.Config;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class Pt215Protocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/Pt3000Protocol.java b/src/main/java/org/traccar/protocol/Pt3000Protocol.java
index d72774f47..5f49084ed 100644
--- a/src/main/java/org/traccar/protocol/Pt3000Protocol.java
+++ b/src/main/java/org/traccar/protocol/Pt3000Protocol.java
@@ -23,7 +23,7 @@ import org.traccar.PipelineBuilder;
import org.traccar.TrackerServer;
import org.traccar.config.Config;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class Pt3000Protocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/Pt502Protocol.java b/src/main/java/org/traccar/protocol/Pt502Protocol.java
index d5d30e8e8..0257dd60f 100644
--- a/src/main/java/org/traccar/protocol/Pt502Protocol.java
+++ b/src/main/java/org/traccar/protocol/Pt502Protocol.java
@@ -22,7 +22,7 @@ import org.traccar.TrackerServer;
import org.traccar.config.Config;
import org.traccar.model.Command;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class Pt502Protocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/Pt60Protocol.java b/src/main/java/org/traccar/protocol/Pt60Protocol.java
index 58345f025..83e3bfbeb 100644
--- a/src/main/java/org/traccar/protocol/Pt60Protocol.java
+++ b/src/main/java/org/traccar/protocol/Pt60Protocol.java
@@ -23,7 +23,7 @@ import org.traccar.PipelineBuilder;
import org.traccar.TrackerServer;
import org.traccar.config.Config;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class Pt60Protocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/PuiProtocol.java b/src/main/java/org/traccar/protocol/PuiProtocol.java
new file mode 100644
index 000000000..ac8291039
--- /dev/null
+++ b/src/main/java/org/traccar/protocol/PuiProtocol.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2023 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.mqtt.MqttDecoder;
+import io.netty.handler.codec.mqtt.MqttEncoder;
+import jakarta.inject.Inject;
+import org.traccar.BaseProtocol;
+import org.traccar.PipelineBuilder;
+import org.traccar.TrackerServer;
+import org.traccar.config.Config;
+
+public class PuiProtocol extends BaseProtocol {
+
+ @Inject
+ public PuiProtocol(Config config) {
+ addServer(new TrackerServer(config, getName(), false) {
+ @Override
+ protected void addProtocolHandlers(PipelineBuilder pipeline, Config config) {
+ pipeline.addLast(MqttEncoder.INSTANCE);
+ pipeline.addLast(new MqttDecoder());
+ pipeline.addLast(new PuiProtocolDecoder(PuiProtocol.this));
+ }
+ });
+ }
+
+}
diff --git a/src/main/java/org/traccar/protocol/PuiProtocolDecoder.java b/src/main/java/org/traccar/protocol/PuiProtocolDecoder.java
new file mode 100644
index 000000000..f10ff3fe7
--- /dev/null
+++ b/src/main/java/org/traccar/protocol/PuiProtocolDecoder.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright 2023 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.mqtt.MqttPublishMessage;
+import jakarta.json.Json;
+import jakarta.json.JsonObject;
+import org.apache.kafka.common.utils.ByteBufferInputStream;
+import org.traccar.BaseMqttProtocolDecoder;
+import org.traccar.Protocol;
+import org.traccar.helper.UnitsConverter;
+import org.traccar.model.Position;
+import org.traccar.session.DeviceSession;
+
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+
+public class PuiProtocolDecoder extends BaseMqttProtocolDecoder {
+
+ public PuiProtocolDecoder(Protocol protocol) {
+ super(protocol);
+ }
+
+ @Override
+ protected Object decode(DeviceSession deviceSession, MqttPublishMessage message) throws Exception {
+
+ JsonObject json;
+ try (ByteBufferInputStream inputStream = new ByteBufferInputStream(message.payload().nioBuffer())) {
+ json = Json.createReader(inputStream).readObject();
+ }
+
+ String type = json.getString("rpt");
+ switch (type) {
+ case "hf":
+ case "loc":
+ Position position = new Position(getProtocolName());
+ position.setDeviceId(deviceSession.getDeviceId());
+
+ position.setValid(true);
+
+ DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
+ position.setTime(dateFormat.parse(json.getString("ts")));
+
+ JsonObject location = json.getJsonObject("location");
+ position.setLatitude(location.getJsonNumber("lat").doubleValue());
+ position.setLongitude(location.getJsonNumber("lon").doubleValue());
+
+ position.setCourse(json.getInt("bear"));
+ position.setSpeed(UnitsConverter.knotsFromCps(json.getInt("spd")));
+
+ position.set(Position.KEY_IGNITION, json.getString("ign").equals("on"));
+
+ return position;
+
+ default:
+ return null;
+ }
+ }
+
+}
diff --git a/src/main/java/org/traccar/protocol/R12wProtocol.java b/src/main/java/org/traccar/protocol/R12wProtocol.java
index a406f6306..b5b3eff81 100644
--- a/src/main/java/org/traccar/protocol/R12wProtocol.java
+++ b/src/main/java/org/traccar/protocol/R12wProtocol.java
@@ -23,7 +23,7 @@ import org.traccar.PipelineBuilder;
import org.traccar.TrackerServer;
import org.traccar.config.Config;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class R12wProtocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/RaceDynamicsProtocol.java b/src/main/java/org/traccar/protocol/RaceDynamicsProtocol.java
index 63ca3476c..6f7340902 100644
--- a/src/main/java/org/traccar/protocol/RaceDynamicsProtocol.java
+++ b/src/main/java/org/traccar/protocol/RaceDynamicsProtocol.java
@@ -23,7 +23,7 @@ import org.traccar.PipelineBuilder;
import org.traccar.TrackerServer;
import org.traccar.config.Config;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class RaceDynamicsProtocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/RadarProtocol.java b/src/main/java/org/traccar/protocol/RadarProtocol.java
index 9d88c6d72..8985e0e83 100644
--- a/src/main/java/org/traccar/protocol/RadarProtocol.java
+++ b/src/main/java/org/traccar/protocol/RadarProtocol.java
@@ -21,7 +21,7 @@ import org.traccar.PipelineBuilder;
import org.traccar.TrackerServer;
import org.traccar.config.Config;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class RadarProtocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/RamacProtocol.java b/src/main/java/org/traccar/protocol/RamacProtocol.java
new file mode 100644
index 000000000..42ce16fe8
--- /dev/null
+++ b/src/main/java/org/traccar/protocol/RamacProtocol.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2023 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.http.HttpObjectAggregator;
+import io.netty.handler.codec.http.HttpRequestDecoder;
+import io.netty.handler.codec.http.HttpResponseEncoder;
+import jakarta.inject.Inject;
+import org.traccar.BaseProtocol;
+import org.traccar.PipelineBuilder;
+import org.traccar.TrackerServer;
+import org.traccar.config.Config;
+
+public class RamacProtocol extends BaseProtocol {
+
+ @Inject
+ public RamacProtocol(Config config) {
+ addServer(new TrackerServer(config, getName(), false) {
+ @Override
+ protected void addProtocolHandlers(PipelineBuilder pipeline, Config config) {
+ pipeline.addLast(new HttpResponseEncoder());
+ pipeline.addLast(new HttpRequestDecoder());
+ pipeline.addLast(new HttpObjectAggregator(65535));
+ pipeline.addLast(new RamacProtocolDecoder(RamacProtocol.this));
+ }
+ });
+ }
+
+}
diff --git a/src/main/java/org/traccar/protocol/RamacProtocolDecoder.java b/src/main/java/org/traccar/protocol/RamacProtocolDecoder.java
new file mode 100644
index 000000000..ffdc68474
--- /dev/null
+++ b/src/main/java/org/traccar/protocol/RamacProtocolDecoder.java
@@ -0,0 +1,112 @@
+/*
+ * Copyright 2023 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.Unpooled;
+import io.netty.channel.Channel;
+import io.netty.handler.codec.http.FullHttpRequest;
+import io.netty.handler.codec.http.HttpResponseStatus;
+import jakarta.json.Json;
+import jakarta.json.JsonObject;
+import org.traccar.BaseHttpProtocolDecoder;
+import org.traccar.Protocol;
+import org.traccar.model.Position;
+import org.traccar.session.DeviceSession;
+
+import java.io.StringReader;
+import java.net.SocketAddress;
+import java.nio.charset.StandardCharsets;
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+
+public class RamacProtocolDecoder extends BaseHttpProtocolDecoder {
+
+ private final DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+
+ public RamacProtocolDecoder(Protocol protocol) {
+ super(protocol);
+ }
+
+ @Override
+ protected Object decode(
+ Channel channel, SocketAddress remoteAddress, Object msg) throws Exception {
+
+ FullHttpRequest request = (FullHttpRequest) msg;
+ String content = request.content().toString(StandardCharsets.UTF_8);
+ JsonObject json = Json.createReader(new StringReader(content)).readObject();
+
+ String deviceId = json.getString("DeviceId");
+ DeviceSession deviceSession = getDeviceSession(channel, remoteAddress, deviceId);
+ if (deviceSession == null) {
+ sendResponse(channel, HttpResponseStatus.BAD_REQUEST);
+ return null;
+ }
+
+ Position position = new Position(getProtocolName());
+ position.setDeviceId(deviceSession.getDeviceId());
+
+ position.set(Position.KEY_TYPE, json.getInt("PacketType"));
+ position.set(Position.KEY_INDEX, json.getInt("SeqNumber"));
+ position.setDeviceTime(dateFormat.parse(json.getString("UpdateDate")));
+
+ int alert = json.getInt("Alert");
+ if (alert > 0) {
+ position.set("alert", alert);
+ String alertMessage = json.getString("AlertMessage");
+ if (!alertMessage.isEmpty()) {
+ position.set("alertMessage", alertMessage);
+ }
+ }
+
+ if (json.containsKey("GpsEvent")) {
+ position.set("gpsEvent", json.getInt("GpsEvent"));
+ if (json.containsKey("GpsEventText")) {
+ position.set("gpsEventText", json.getString("GpsEventText"));
+ }
+ }
+
+ if (json.containsKey("Event")) {
+ position.set(Position.KEY_EVENT, json.getInt("Event"));
+ }
+ if (json.containsKey("BatteryPercentage")) {
+ position.set(Position.KEY_BATTERY_LEVEL, json.getInt("BatteryPercentage"));
+ }
+ if (json.containsKey("Battery")) {
+ position.set(Position.KEY_BATTERY, json.getJsonNumber("Battery").doubleValue());
+ }
+
+ position.set("deviceType", json.getString("DeviceTypeText"));
+
+ if (json.containsKey("Latitude") && json.containsKey("Longitude")) {
+ position.setValid(true);
+ if (json.containsKey("LocationDateTime")) {
+ position.setFixTime(dateFormat.parse(json.getString("LocationDateTime")));
+ } else {
+ position.setFixTime(position.getDeviceTime());
+ }
+ position.setLatitude(json.getJsonNumber("Latitude").doubleValue());
+ position.setLongitude(json.getJsonNumber("Longitude").doubleValue());
+ } else {
+ getLastLocation(position, position.getDeviceTime());
+ }
+
+ sendResponse(
+ channel, HttpResponseStatus.OK,
+ Unpooled.copiedBuffer("{\"CaseID\":1,\"EventID\":1}", StandardCharsets.UTF_8));
+ return position;
+ }
+
+}
diff --git a/src/main/java/org/traccar/protocol/RaveonProtocol.java b/src/main/java/org/traccar/protocol/RaveonProtocol.java
index db70396ee..aa1a79219 100644
--- a/src/main/java/org/traccar/protocol/RaveonProtocol.java
+++ b/src/main/java/org/traccar/protocol/RaveonProtocol.java
@@ -23,7 +23,7 @@ import org.traccar.PipelineBuilder;
import org.traccar.TrackerServer;
import org.traccar.config.Config;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class RaveonProtocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/RecodaProtocol.java b/src/main/java/org/traccar/protocol/RecodaProtocol.java
index 0d50db01e..7d2fadae4 100644
--- a/src/main/java/org/traccar/protocol/RecodaProtocol.java
+++ b/src/main/java/org/traccar/protocol/RecodaProtocol.java
@@ -22,7 +22,7 @@ import org.traccar.TrackerServer;
import org.traccar.config.Config;
import java.nio.ByteOrder;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class RecodaProtocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/RetranslatorProtocol.java b/src/main/java/org/traccar/protocol/RetranslatorProtocol.java
index 1d4b419bb..a349a8191 100644
--- a/src/main/java/org/traccar/protocol/RetranslatorProtocol.java
+++ b/src/main/java/org/traccar/protocol/RetranslatorProtocol.java
@@ -20,7 +20,7 @@ import org.traccar.PipelineBuilder;
import org.traccar.TrackerServer;
import org.traccar.config.Config;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class RetranslatorProtocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/RfTrackProtocol.java b/src/main/java/org/traccar/protocol/RfTrackProtocol.java
index d3b41e93e..ac033c348 100644
--- a/src/main/java/org/traccar/protocol/RfTrackProtocol.java
+++ b/src/main/java/org/traccar/protocol/RfTrackProtocol.java
@@ -23,7 +23,7 @@ import org.traccar.PipelineBuilder;
import org.traccar.TrackerServer;
import org.traccar.config.Config;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class RfTrackProtocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/RfTrackProtocolDecoder.java b/src/main/java/org/traccar/protocol/RfTrackProtocolDecoder.java
index 28a3ac29c..cbb204e3b 100644
--- a/src/main/java/org/traccar/protocol/RfTrackProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/RfTrackProtocolDecoder.java
@@ -29,9 +29,9 @@ import org.traccar.model.Position;
import org.traccar.model.WifiAccessPoint;
import org.traccar.session.DeviceSession;
-import javax.json.Json;
-import javax.json.JsonArray;
-import javax.json.JsonObject;
+import jakarta.json.Json;
+import jakarta.json.JsonArray;
+import jakarta.json.JsonObject;
import java.io.StringReader;
import java.net.SocketAddress;
import java.nio.charset.StandardCharsets;
diff --git a/src/main/java/org/traccar/protocol/RitiProtocol.java b/src/main/java/org/traccar/protocol/RitiProtocol.java
index 9b9c00cb2..9916042a8 100644
--- a/src/main/java/org/traccar/protocol/RitiProtocol.java
+++ b/src/main/java/org/traccar/protocol/RitiProtocol.java
@@ -22,7 +22,7 @@ import org.traccar.TrackerServer;
import org.traccar.config.Config;
import java.nio.ByteOrder;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class RitiProtocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/RoboTrackProtocol.java b/src/main/java/org/traccar/protocol/RoboTrackProtocol.java
index ab2bc5842..229c343bb 100644
--- a/src/main/java/org/traccar/protocol/RoboTrackProtocol.java
+++ b/src/main/java/org/traccar/protocol/RoboTrackProtocol.java
@@ -20,7 +20,7 @@ import org.traccar.PipelineBuilder;
import org.traccar.TrackerServer;
import org.traccar.config.Config;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class RoboTrackProtocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/RstProtocol.java b/src/main/java/org/traccar/protocol/RstProtocol.java
index 109d91b16..0bb809a49 100644
--- a/src/main/java/org/traccar/protocol/RstProtocol.java
+++ b/src/main/java/org/traccar/protocol/RstProtocol.java
@@ -22,7 +22,7 @@ import org.traccar.PipelineBuilder;
import org.traccar.TrackerServer;
import org.traccar.config.Config;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class RstProtocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/RstProtocolDecoder.java b/src/main/java/org/traccar/protocol/RstProtocolDecoder.java
index fcc96fbf1..eafa4d3d7 100644
--- a/src/main/java/org/traccar/protocol/RstProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/RstProtocolDecoder.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2019 - 2021 Anton Tananaev (anton@traccar.org)
+ * Copyright 2019 - 2024 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.
@@ -69,8 +69,10 @@ public class RstProtocolDecoder extends BaseProtocolDecoder {
.number("x{4};") // sensors
.number("(xx);") // status 1
.number("(xx);") // status 2
+ .expression("(.*)") // additional data
.groupEnd("?")
.any()
+ .text("FIM;")
.compile();
@Override
@@ -115,9 +117,16 @@ public class RstProtocolDecoder extends BaseProtocolDecoder {
position.set(Position.KEY_SATELLITES, parser.nextInt());
position.set(Position.KEY_HDOP, parser.nextInt());
- position.set(Position.PREFIX_IN + 1, parser.nextHexInt());
- position.set(Position.PREFIX_IN + 2, parser.nextHexInt());
- position.set(Position.PREFIX_IN + 3, parser.nextHexInt());
+
+ int inputs1 = parser.nextHexInt();
+ int inputs2 = parser.nextHexInt();
+ int inputs3 = parser.nextHexInt();
+ position.set(Position.PREFIX_IN + 1, inputs1);
+ position.set(Position.PREFIX_IN + 2, inputs2);
+ position.set(Position.PREFIX_IN + 3, inputs3);
+
+ position.set(Position.KEY_IGNITION, BitUtil.check(inputs2, 7));
+
position.set(Position.PREFIX_OUT + 1, parser.nextHexInt());
position.set(Position.PREFIX_OUT + 2, parser.nextHexInt());
position.set(Position.KEY_POWER, parser.nextDouble());
@@ -125,10 +134,23 @@ public class RstProtocolDecoder extends BaseProtocolDecoder {
position.set(Position.KEY_ODOMETER, parser.nextInt());
position.set(Position.KEY_RSSI, parser.nextInt());
position.set(Position.PREFIX_TEMP + 1, (int) parser.nextHexInt().byteValue());
+ position.set(Position.KEY_STATUS, (parser.nextHexInt() << 8) + parser.nextHexInt());
+
+ String[] values = parser.next().split(";");
+ if (type == 55) {
+ position.set(Position.KEY_DRIVER_UNIQUE_ID, values[0]);
+ }
+
+ return position;
+
+ } else if (type == 134) {
+
+ Position position = new Position(getProtocolName());
+ position.setDeviceId(deviceSession.getDeviceId());
+
+ getLastLocation(position, null);
- int status = (parser.nextHexInt() << 8) + parser.nextHexInt();
- position.set(Position.KEY_IGNITION, BitUtil.check(status, 7));
- position.set(Position.KEY_STATUS, status);
+ position.set(Position.KEY_RESULT, String.valueOf(type));
return position;
diff --git a/src/main/java/org/traccar/protocol/RuptelaProtocol.java b/src/main/java/org/traccar/protocol/RuptelaProtocol.java
index 99a9686f6..9f399e299 100644
--- a/src/main/java/org/traccar/protocol/RuptelaProtocol.java
+++ b/src/main/java/org/traccar/protocol/RuptelaProtocol.java
@@ -22,7 +22,7 @@ import org.traccar.TrackerServer;
import org.traccar.config.Config;
import org.traccar.model.Command;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class RuptelaProtocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/RuptelaProtocolDecoder.java b/src/main/java/org/traccar/protocol/RuptelaProtocolDecoder.java
index 77df0deb7..e1efb5757 100644
--- a/src/main/java/org/traccar/protocol/RuptelaProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/RuptelaProtocolDecoder.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2013 - 2022 Anton Tananaev (anton@traccar.org)
+ * Copyright 2013 - 2024 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.
@@ -22,6 +22,7 @@ import org.traccar.BaseProtocolDecoder;
import org.traccar.session.DeviceSession;
import org.traccar.NetworkMessage;
import org.traccar.Protocol;
+import org.traccar.helper.BitUtil;
import org.traccar.helper.DataConverter;
import org.traccar.helper.UnitsConverter;
import org.traccar.model.Position;
@@ -50,6 +51,7 @@ public class RuptelaProtocolDecoder extends BaseProtocolDecoder {
public static final int MSG_SMS_VIA_GPRS = 8;
public static final int MSG_DTCS = 9;
public static final int MSG_IDENTIFICATION = 15;
+ public static final int MSG_HEARTBEAT = 16;
public static final int MSG_SET_IO = 17;
public static final int MSG_FILES = 37;
public static final int MSG_EXTENDED_RECORDS = 68;
@@ -92,22 +94,55 @@ public class RuptelaProtocolDecoder extends BaseProtocolDecoder {
}
}
+ private void decodeDriver(Position position, String part1, String part2) {
+ Long driverIdPart1 = (Long) position.getAttributes().remove(part1);
+ Long driverIdPart2 = (Long) position.getAttributes().remove(part2);
+ if (driverIdPart1 != null && driverIdPart2 != null) {
+ ByteBuf driverId = Unpooled.copyLong(driverIdPart1, driverIdPart2);
+ position.set(Position.KEY_DRIVER_UNIQUE_ID, driverId.toString(StandardCharsets.US_ASCII));
+ driverId.release();
+ }
+ }
+
private void decodeParameter(Position position, int id, ByteBuf buf, int length) {
switch (id) {
case 2:
case 3:
case 4:
- position.set("di" + (id - 1), readValue(buf, length, false));
- break;
case 5:
- position.set(Position.KEY_IGNITION, readValue(buf, length, false) == 1);
+ position.set(Position.PREFIX_IN + (id - 1), readValue(buf, length, false));
+ break;
+ case 13:
+ case 173:
+ position.set(Position.KEY_MOTION, readValue(buf, length, false) > 0);
+ break;
+ case 20:
+ position.set(Position.PREFIX_ADC + 3, readValue(buf, length, false));
+ break;
+ case 21:
+ position.set(Position.PREFIX_ADC + 4, readValue(buf, length, false));
+ break;
+ case 22:
+ position.set(Position.PREFIX_ADC + 1, readValue(buf, length, false));
+ break;
+ case 23:
+ position.set(Position.PREFIX_ADC + 2, readValue(buf, length, false));
break;
case 29:
- position.set(Position.KEY_POWER, readValue(buf, length, false));
+ position.set(Position.KEY_POWER, readValue(buf, length, false) * 0.001);
break;
case 30:
position.set(Position.KEY_BATTERY, readValue(buf, length, false) * 0.001);
break;
+ case 32:
+ position.set(Position.KEY_DEVICE_TEMP, readValue(buf, length, true));
+ break;
+ case 39:
+ position.set(Position.KEY_ENGINE_LOAD, readValue(buf, length, false));
+ break;
+ case 65:
+ position.set(Position.KEY_ODOMETER, readValue(buf, length, false));
+ break;
case 74:
position.set(Position.PREFIX_TEMP + 3, readValue(buf, length, true) * 0.1);
break;
@@ -116,6 +151,23 @@ public class RuptelaProtocolDecoder extends BaseProtocolDecoder {
case 80:
position.set(Position.PREFIX_TEMP + (id - 78), readValue(buf, length, true) * 0.1);
break;
+ case 88:
+ if (readValue(buf, length, false) > 0) {
+ position.set(Position.KEY_ALARM, Position.ALARM_JAMMING);
+ }
+ break;
+ case 94:
+ position.set(Position.KEY_RPM, readValue(buf, length, false) * 0.25);
+ break;
+ case 95:
+ position.set(Position.KEY_OBD_SPEED, readValue(buf, length, false));
+ break;
+ case 98:
+ position.set(Position.KEY_FUEL_LEVEL, readValue(buf, length, false) * 100 / 255.0);
+ break;
+ case 100:
+ position.set(Position.KEY_FUEL_CONSUMPTION, readValue(buf, length, false) / 20.0);
+ break;
case 134:
if (readValue(buf, length, false) > 0) {
position.set(Position.KEY_ALARM, Position.ALARM_BRAKING);
@@ -126,9 +178,61 @@ public class RuptelaProtocolDecoder extends BaseProtocolDecoder {
position.set(Position.KEY_ALARM, Position.ALARM_ACCELERATION);
}
break;
+ case 150:
+ position.set(Position.KEY_OPERATOR, readValue(buf, length, false));
+ break;
+ case 163:
+ position.set(Position.KEY_ODOMETER, readValue(buf, length, false) * 5);
+ break;
+ case 164:
+ position.set(Position.KEY_ODOMETER_TRIP, readValue(buf, length, false) * 5);
+ break;
+ case 165:
+ position.set(Position.KEY_OBD_SPEED, readValue(buf, length, false) / 256.0);
+ break;
+ case 166:
case 197:
position.set(Position.KEY_RPM, readValue(buf, length, false) * 0.125);
break;
+ case 170:
+ position.set(Position.KEY_CHARGE, readValue(buf, length, false) > 0);
+ break;
+ case 205:
+ position.set(Position.KEY_FUEL_LEVEL, readValue(buf, length, false));
+ break;
+ case 207:
+ position.set(Position.KEY_FUEL_LEVEL, readValue(buf, length, false) * 0.4);
+ break;
+ case 208:
+ position.set(Position.KEY_FUEL_USED, readValue(buf, length, false) * 0.5);
+ break;
+ case 251:
+ case 409:
+ position.set(Position.KEY_IGNITION, readValue(buf, length, false) > 0);
+ break;
+ case 410:
+ if (readValue(buf, length, false) > 0) {
+ position.set(Position.KEY_ALARM, Position.ALARM_TOW);
+ }
+ break;
+ case 411:
+ if (readValue(buf, length, false) > 0) {
+ position.set(Position.KEY_ALARM, Position.ALARM_ACCIDENT);
+ }
+ break;
+ case 415:
+ if (readValue(buf, length, false) == 0) {
+ position.set(Position.KEY_ALARM, Position.ALARM_GPS_ANTENNA_CUT);
+ }
+ break;
+ case 645:
+ position.set(Position.KEY_OBD_ODOMETER, readValue(buf, length, false) * 1000);
+ break;
+ case 758:
+ if (readValue(buf, length, false) == 1) {
+ position.set(Position.KEY_ALARM, Position.ALARM_TAMPERING);
+ }
+ break;
default:
position.set(Position.PREFIX_IO + id, readValue(buf, length, false));
break;
@@ -166,22 +270,36 @@ public class RuptelaProtocolDecoder extends BaseProtocolDecoder {
buf.readUnsignedByte(); // timestamp extension
if (type == MSG_EXTENDED_RECORDS) {
- buf.readUnsignedByte(); // record extension
+ int recordExtension = buf.readUnsignedByte();
+ int mergeRecordCount = BitUtil.from(recordExtension, 4);
+ int currentRecord = BitUtil.to(recordExtension, 4);
+
+ if (currentRecord > 0 && currentRecord <= mergeRecordCount) {
+ if (positions.size() == 0) {
+ getLastLocation(position, null);
+ } else {
+ position = positions.remove(positions.size() - 1);
+ }
+ }
}
buf.readUnsignedByte(); // priority (reserved)
- position.setValid(true);
- position.setLongitude(buf.readInt() / 10000000.0);
- position.setLatitude(buf.readInt() / 10000000.0);
- position.setAltitude(buf.readUnsignedShort() / 10.0);
- position.setCourse(buf.readUnsignedShort() / 100.0);
-
- position.set(Position.KEY_SATELLITES, buf.readUnsignedByte());
-
- position.setSpeed(UnitsConverter.knotsFromKph(buf.readUnsignedShort()));
-
- position.set(Position.KEY_HDOP, buf.readUnsignedByte() / 10.0);
+ int longitude = buf.readInt();
+ int latitude = buf.readInt();
+ if (longitude > Integer.MIN_VALUE && latitude > Integer.MIN_VALUE) {
+ position.setValid(true);
+ position.setLongitude(longitude / 10000000.0);
+ position.setLatitude(latitude / 10000000.0);
+ position.setAltitude(buf.readUnsignedShort() / 10.0);
+ position.setCourse(buf.readUnsignedShort() / 100.0);
+ position.set(Position.KEY_SATELLITES, buf.readUnsignedByte());
+ position.setSpeed(UnitsConverter.knotsFromKph(buf.readUnsignedShort()));
+ position.set(Position.KEY_HDOP, buf.readUnsignedByte() / 10.0);
+ } else {
+ buf.skipBytes(8);
+ getLastLocation(position, null);
+ }
if (type == MSG_EXTENDED_RECORDS) {
position.set(Position.KEY_EVENT, buf.readUnsignedShort());
@@ -217,12 +335,13 @@ public class RuptelaProtocolDecoder extends BaseProtocolDecoder {
decodeParameter(position, id, buf, 8);
}
- Long driverIdPart1 = (Long) position.getAttributes().remove(Position.PREFIX_IO + 126);
- Long driverIdPart2 = (Long) position.getAttributes().remove(Position.PREFIX_IO + 127);
- if (driverIdPart1 != null && driverIdPart2 != null) {
- ByteBuf driverId = Unpooled.copyLong(driverIdPart1, driverIdPart2);
- position.set(Position.KEY_DRIVER_UNIQUE_ID, driverId.toString(StandardCharsets.US_ASCII));
- driverId.release();
+ decodeDriver(position, Position.PREFIX_IO + 126, Position.PREFIX_IO + 127); // can driver
+ decodeDriver(position, Position.PREFIX_IO + 155, Position.PREFIX_IO + 156); // tco driver
+
+ Long tagIdPart1 = (Long) position.getAttributes().remove(Position.PREFIX_IO + 760);
+ Long tagIdPart2 = (Long) position.getAttributes().remove(Position.PREFIX_IO + 761);
+ if (tagIdPart1 != null && tagIdPart2 != null) {
+ position.set("tagId", Long.toHexString(tagIdPart1) + Long.toHexString(tagIdPart2));
}
positions.add(position);
@@ -306,7 +425,7 @@ public class RuptelaProtocolDecoder extends BaseProtocolDecoder {
return null;
- } else if (type == MSG_IDENTIFICATION) {
+ } else if (type == MSG_IDENTIFICATION || type == MSG_HEARTBEAT) {
ByteBuf content = Unpooled.buffer();
content.writeByte(1);
diff --git a/src/main/java/org/traccar/protocol/S168Protocol.java b/src/main/java/org/traccar/protocol/S168Protocol.java
index f904ed9ff..5fb0c6e72 100644
--- a/src/main/java/org/traccar/protocol/S168Protocol.java
+++ b/src/main/java/org/traccar/protocol/S168Protocol.java
@@ -23,7 +23,7 @@ import org.traccar.PipelineBuilder;
import org.traccar.TrackerServer;
import org.traccar.config.Config;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class S168Protocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/SabertekProtocol.java b/src/main/java/org/traccar/protocol/SabertekProtocol.java
index 403243cdc..cb3f2ab32 100644
--- a/src/main/java/org/traccar/protocol/SabertekProtocol.java
+++ b/src/main/java/org/traccar/protocol/SabertekProtocol.java
@@ -21,7 +21,7 @@ import org.traccar.PipelineBuilder;
import org.traccar.TrackerServer;
import org.traccar.config.Config;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class SabertekProtocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/SanavProtocol.java b/src/main/java/org/traccar/protocol/SanavProtocol.java
index 1a0e7b0e9..ac1941725 100644
--- a/src/main/java/org/traccar/protocol/SanavProtocol.java
+++ b/src/main/java/org/traccar/protocol/SanavProtocol.java
@@ -22,7 +22,7 @@ import org.traccar.PipelineBuilder;
import org.traccar.TrackerServer;
import org.traccar.config.Config;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class SanavProtocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/SanulProtocol.java b/src/main/java/org/traccar/protocol/SanulProtocol.java
index ea44bf868..cba162296 100644
--- a/src/main/java/org/traccar/protocol/SanulProtocol.java
+++ b/src/main/java/org/traccar/protocol/SanulProtocol.java
@@ -23,7 +23,7 @@ import org.traccar.config.Config;
import java.nio.ByteOrder;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class SanulProtocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/SatsolProtocol.java b/src/main/java/org/traccar/protocol/SatsolProtocol.java
index d90033e38..7252f99f0 100644
--- a/src/main/java/org/traccar/protocol/SatsolProtocol.java
+++ b/src/main/java/org/traccar/protocol/SatsolProtocol.java
@@ -23,7 +23,7 @@ import org.traccar.config.Config;
import java.nio.ByteOrder;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class SatsolProtocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/SigfoxProtocol.java b/src/main/java/org/traccar/protocol/SigfoxProtocol.java
index 9a268af62..edd624727 100644
--- a/src/main/java/org/traccar/protocol/SigfoxProtocol.java
+++ b/src/main/java/org/traccar/protocol/SigfoxProtocol.java
@@ -23,7 +23,7 @@ import org.traccar.PipelineBuilder;
import org.traccar.TrackerServer;
import org.traccar.config.Config;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class SigfoxProtocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/SigfoxProtocolDecoder.java b/src/main/java/org/traccar/protocol/SigfoxProtocolDecoder.java
index 4ed2bb51d..e0dfab9b2 100644
--- a/src/main/java/org/traccar/protocol/SigfoxProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/SigfoxProtocolDecoder.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2017 - 2020 Anton Tananaev (anton@traccar.org)
+ * Copyright 2017 - 2024 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.
@@ -32,11 +32,11 @@ import org.traccar.model.Network;
import org.traccar.model.Position;
import org.traccar.model.WifiAccessPoint;
-import javax.json.Json;
-import javax.json.JsonNumber;
-import javax.json.JsonObject;
-import javax.json.JsonString;
-import javax.json.JsonValue;
+import jakarta.json.Json;
+import jakarta.json.JsonNumber;
+import jakarta.json.JsonObject;
+import jakarta.json.JsonString;
+import jakarta.json.JsonValue;
import java.io.StringReader;
import java.net.SocketAddress;
import java.net.URLDecoder;
@@ -105,7 +105,7 @@ public class SigfoxProtocolDecoder extends BaseHttpProtocolDecoder {
FullHttpRequest request = (FullHttpRequest) msg;
String content = request.content().toString(StandardCharsets.UTF_8);
if (!content.startsWith("{")) {
- content = URLDecoder.decode(content.split("=")[0], "UTF-8");
+ content = URLDecoder.decode(content.split("=")[0], StandardCharsets.UTF_8);
}
JsonObject json = Json.createReader(new StringReader(content)).readObject();
@@ -156,18 +156,30 @@ public class SigfoxProtocolDecoder extends BaseHttpProtocolDecoder {
ByteBuf buf = Unpooled.wrappedBuffer(DataConverter.parseHex(json.getString("data")));
try {
- int event = buf.readUnsignedByte();
- if (event == 0x0f || event == 0x1f) {
+ int header = buf.readUnsignedByte();
+ if ("Amber".equals(getDeviceModel(deviceSession))) {
+
+ int flags = buf.readUnsignedByte();
+ position.set(Position.KEY_MOTION, BitUtil.check(flags, 1));
+
+ position.set(Position.KEY_BATTERY, buf.readUnsignedByte() * 0.02);
+ position.set(Position.PREFIX_TEMP + 1, (int) buf.readByte());
+
+ position.setValid(true);
+ position.setLatitude(buf.readInt() / 60000.0);
+ position.setLongitude(buf.readInt() / 60000.0);
+
+ } else if (header == 0x0f || header == 0x1f) {
- position.setValid(event >> 4 > 0);
+ position.setValid(header >> 4 > 0);
position.setLatitude(BufferUtil.readSignedMagnitudeInt(buf) * 0.000001);
position.setLongitude(BufferUtil.readSignedMagnitudeInt(buf) * 0.000001);
position.set(Position.KEY_BATTERY, (int) buf.readUnsignedByte());
- } else if (event >> 4 <= 3 && buf.writerIndex() == 12) {
+ } else if (header >> 4 <= 3 && buf.writerIndex() == 12) {
- if (BitUtil.to(event, 4) == 0) {
+ if (BitUtil.to(header, 4) == 0) {
position.setValid(true);
position.setLatitude(buf.readIntLE() * 0.0000001);
position.setLongitude(buf.readIntLE() * 0.0000001);
diff --git a/src/main/java/org/traccar/protocol/SiwiProtocol.java b/src/main/java/org/traccar/protocol/SiwiProtocol.java
index f12958a50..59b96bf72 100644
--- a/src/main/java/org/traccar/protocol/SiwiProtocol.java
+++ b/src/main/java/org/traccar/protocol/SiwiProtocol.java
@@ -22,7 +22,7 @@ import org.traccar.PipelineBuilder;
import org.traccar.TrackerServer;
import org.traccar.config.Config;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class SiwiProtocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/SkypatrolProtocol.java b/src/main/java/org/traccar/protocol/SkypatrolProtocol.java
index 7ae26f634..615ef536d 100644
--- a/src/main/java/org/traccar/protocol/SkypatrolProtocol.java
+++ b/src/main/java/org/traccar/protocol/SkypatrolProtocol.java
@@ -20,7 +20,7 @@ import org.traccar.PipelineBuilder;
import org.traccar.TrackerServer;
import org.traccar.config.Config;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class SkypatrolProtocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/SmartSoleProtocol.java b/src/main/java/org/traccar/protocol/SmartSoleProtocol.java
index cb7efb7ee..e4838581a 100644
--- a/src/main/java/org/traccar/protocol/SmartSoleProtocol.java
+++ b/src/main/java/org/traccar/protocol/SmartSoleProtocol.java
@@ -23,7 +23,7 @@ import org.traccar.PipelineBuilder;
import org.traccar.TrackerServer;
import org.traccar.config.Config;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class SmartSoleProtocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/SmokeyProtocol.java b/src/main/java/org/traccar/protocol/SmokeyProtocol.java
index 22b343537..0aa2bcfa7 100644
--- a/src/main/java/org/traccar/protocol/SmokeyProtocol.java
+++ b/src/main/java/org/traccar/protocol/SmokeyProtocol.java
@@ -20,7 +20,7 @@ import org.traccar.PipelineBuilder;
import org.traccar.TrackerServer;
import org.traccar.config.Config;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class SmokeyProtocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/SolarPoweredProtocol.java b/src/main/java/org/traccar/protocol/SolarPoweredProtocol.java
index 0676aa629..e00f27b9b 100644
--- a/src/main/java/org/traccar/protocol/SolarPoweredProtocol.java
+++ b/src/main/java/org/traccar/protocol/SolarPoweredProtocol.java
@@ -20,7 +20,7 @@ import org.traccar.PipelineBuilder;
import org.traccar.TrackerServer;
import org.traccar.config.Config;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class SolarPoweredProtocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/SpotProtocol.java b/src/main/java/org/traccar/protocol/SpotProtocol.java
index 6bd802fed..4fc57f177 100644
--- a/src/main/java/org/traccar/protocol/SpotProtocol.java
+++ b/src/main/java/org/traccar/protocol/SpotProtocol.java
@@ -23,7 +23,7 @@ import org.traccar.PipelineBuilder;
import org.traccar.TrackerServer;
import org.traccar.config.Config;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class SpotProtocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/StarLinkProtocol.java b/src/main/java/org/traccar/protocol/StarLinkProtocol.java
index d578fa705..6dcd40fbf 100644
--- a/src/main/java/org/traccar/protocol/StarLinkProtocol.java
+++ b/src/main/java/org/traccar/protocol/StarLinkProtocol.java
@@ -23,7 +23,7 @@ import org.traccar.PipelineBuilder;
import org.traccar.TrackerServer;
import org.traccar.config.Config;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class StarLinkProtocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/StarLinkProtocolDecoder.java b/src/main/java/org/traccar/protocol/StarLinkProtocolDecoder.java
index aa23bfac5..193005e28 100644
--- a/src/main/java/org/traccar/protocol/StarLinkProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/StarLinkProtocolDecoder.java
@@ -61,10 +61,10 @@ public class StarLinkProtocolDecoder extends BaseProtocolDecoder {
@Override
protected void init() {
setFormat(getConfig().getString(
- getProtocolName() + ".format", "#EDT#,#EID#,#PDT#,#LAT#,#LONG#,#SPD#,#HEAD#,#ODO#,"
+ Keys.PROTOCOL_FORMAT.withPrefix(getProtocolName()), "#EDT#,#EID#,#PDT#,#LAT#,#LONG#,#SPD#,#HEAD#,#ODO#,"
+ "#IN1#,#IN2#,#IN3#,#IN4#,#OUT1#,#OUT2#,#OUT3#,#OUT4#,#LAC#,#CID#,#VIN#,#VBAT#,#DEST#,#IGN#,#ENG#"));
- setDateFormat(getConfig().getString(getProtocolName() + ".dateFormat", "yyMMddHHmmss"));
+ setDateFormat(getConfig().getString(Keys.PROTOCOL_DATE_FORMAT.withPrefix(getProtocolName()), "yyMMddHHmmss"));
}
public String[] getFormat(long deviceId) {
diff --git a/src/main/java/org/traccar/protocol/StarcomProtocol.java b/src/main/java/org/traccar/protocol/StarcomProtocol.java
index 33c3a4776..458220e59 100644
--- a/src/main/java/org/traccar/protocol/StarcomProtocol.java
+++ b/src/main/java/org/traccar/protocol/StarcomProtocol.java
@@ -22,7 +22,7 @@ import org.traccar.PipelineBuilder;
import org.traccar.TrackerServer;
import org.traccar.config.Config;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class StarcomProtocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/StarcomProtocolDecoder.java b/src/main/java/org/traccar/protocol/StarcomProtocolDecoder.java
index 56ab733c8..325847b16 100644
--- a/src/main/java/org/traccar/protocol/StarcomProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/StarcomProtocolDecoder.java
@@ -75,7 +75,7 @@ public class StarcomProtocolDecoder extends BaseProtocolDecoder {
case "eventid":
position.set(Position.KEY_EVENT, Integer.parseInt(value));
break;
- case "mileage":
+ case "odometer":
position.set(Position.KEY_ODOMETER, (long) (Double.parseDouble(value) * 1000));
break;
case "satellites":
@@ -110,8 +110,8 @@ public class StarcomProtocolDecoder extends BaseProtocolDecoder {
case "extra1":
case "extra2":
case "extra3":
- position.set(key, value);
default:
+ position.set(key, value);
break;
}
}
diff --git a/src/main/java/org/traccar/protocol/NdtpV6FrameDecoder.java b/src/main/java/org/traccar/protocol/StartekFrameDecoder.java
index 5b610013a..608b128cd 100644
--- a/src/main/java/org/traccar/protocol/NdtpV6FrameDecoder.java
+++ b/src/main/java/org/traccar/protocol/StartekFrameDecoder.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2022 Anton Tananaev (anton@traccar.org)
+ * Copyright 2024 Anton Tananaev (anton@traccar.org)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -20,13 +20,30 @@ import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import org.traccar.BaseFrameDecoder;
-public class NdtpV6FrameDecoder extends BaseFrameDecoder {
+import java.nio.charset.StandardCharsets;
+
+public class StartekFrameDecoder extends BaseFrameDecoder {
@Override
protected Object decode(
ChannelHandlerContext ctx, Channel channel, ByteBuf buf) throws Exception {
- return buf;
+ if (buf.readableBytes() < 10) {
+ return null;
+ }
+
+ int lengthIndex = buf.readerIndex() + 3;
+ int dividerIndex = buf.indexOf(lengthIndex, buf.writerIndex(), (byte) ',');
+ if (dividerIndex > 0) {
+ int lengthOffset = dividerIndex - buf.readerIndex() + 4;
+ int length = lengthOffset + Integer.parseInt(buf.getCharSequence(
+ lengthIndex, dividerIndex - lengthIndex, StandardCharsets.US_ASCII).toString());
+ if (buf.readableBytes() >= length) {
+ return buf.readRetainedSlice(length);
+ }
+ }
+
+ return null;
}
}
diff --git a/src/main/java/org/traccar/protocol/StartekProtocol.java b/src/main/java/org/traccar/protocol/StartekProtocol.java
index d010df858..9c01d24e2 100644
--- a/src/main/java/org/traccar/protocol/StartekProtocol.java
+++ b/src/main/java/org/traccar/protocol/StartekProtocol.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2021 Anton Tananaev (anton@traccar.org)
+ * Copyright 2021 - 2024 Anton Tananaev (anton@traccar.org)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -15,7 +15,6 @@
*/
package org.traccar.protocol;
-import io.netty.handler.codec.LineBasedFrameDecoder;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;
import org.traccar.BaseProtocol;
@@ -24,7 +23,7 @@ import org.traccar.TrackerServer;
import org.traccar.config.Config;
import org.traccar.model.Command;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class StartekProtocol extends BaseProtocol {
@@ -38,7 +37,7 @@ public class StartekProtocol extends BaseProtocol {
addServer(new TrackerServer(config, getName(), false) {
@Override
protected void addProtocolHandlers(PipelineBuilder pipeline, Config config) {
- pipeline.addLast(new LineBasedFrameDecoder(1024));
+ pipeline.addLast(new StartekFrameDecoder());
pipeline.addLast(new StringEncoder());
pipeline.addLast(new StringDecoder());
pipeline.addLast(new StartekProtocolEncoder(StartekProtocol.this));
diff --git a/src/main/java/org/traccar/protocol/StartekProtocolDecoder.java b/src/main/java/org/traccar/protocol/StartekProtocolDecoder.java
index 8e3624cb5..0eeb5b2aa 100644
--- a/src/main/java/org/traccar/protocol/StartekProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/StartekProtocolDecoder.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2021 - 2022 Anton Tananaev (anton@traccar.org)
+ * Copyright 2021 - 2024 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.
@@ -41,12 +41,13 @@ public class StartekProtocolDecoder extends BaseProtocolDecoder {
.expression(".") // index
.number("d+,") // length
.number("(d+),") // imei
+ .number("(xxx),") // type
.expression("(.+)") // content
.number("xx") // checksum
+ .text("\r\n")
.compile();
private static final Pattern PATTERN_POSITION = new PatternBuilder()
- .number("xxx,") // command
.number("(d+),") // event
.expression("([^,]+)?,") // event data
.number("(dd)(dd)(dd)") // date (yyymmdd)
@@ -72,12 +73,10 @@ public class StartekProtocolDecoder extends BaseProtocolDecoder {
.number("(x+)") // battery
.expression("([^,]+)?") // adc
.groupBegin()
- .text(",")
- .number("d,") // extended
- .expression("([^,]+)?") // fuel
+ .number(",d+") // extended
+ .expression(",([^,]+)?") // fuel
.groupBegin()
- .text(",")
- .expression("([^,]+)?") // temperature
+ .expression(",([^,]+)?") // temperature
.groupBegin()
.text(",")
.groupBegin()
@@ -91,16 +90,26 @@ public class StartekProtocolDecoder extends BaseProtocolDecoder {
.number("(d+)?|") // instant fuel
.number("(d+)[%L]").optional() // fuel level
.groupEnd("?")
+ .number(",(d+)").optional() // hours
.groupEnd("?")
.groupEnd("?")
.groupEnd("?")
+ .any()
.compile();
private String decodeAlarm(int value) {
switch (value) {
+ case 1:
+ return Position.ALARM_SOS;
case 5:
case 6:
return Position.ALARM_DOOR;
+ case 17:
+ return Position.ALARM_LOW_POWER;
+ case 18:
+ return Position.ALARM_POWER_CUT;
+ case 19:
+ return Position.ALARM_POWER_RESTORED;
case 39:
return Position.ALARM_ACCELERATION;
case 40:
@@ -126,26 +135,24 @@ public class StartekProtocolDecoder extends BaseProtocolDecoder {
return null;
}
+ String type = parser.next();
String content = parser.next();
- if (content.length() < 100) {
-
- Position position = new Position(getProtocolName());
- position.setDeviceId(deviceSession.getDeviceId());
-
- getLastLocation(position, null);
-
- position.set(Position.KEY_RESULT, content);
-
- return position;
-
- } else {
-
- return decodePosition(deviceSession, content);
-
+ switch (type) {
+ case "000":
+ return decodePosition(deviceSession, content);
+ case "710":
+ return decodeSerial(deviceSession, content);
+ default:
+ Position position = new Position(getProtocolName());
+ position.setDeviceId(deviceSession.getDeviceId());
+ getLastLocation(position, null);
+ position.set(Position.KEY_TYPE, type);
+ position.set(Position.KEY_RESULT, content);
+ return position;
}
}
- protected Object decodePosition(DeviceSession deviceSession, String content) throws Exception {
+ private Object decodePosition(DeviceSession deviceSession, String content) {
Parser parser = new Parser(PATTERN_POSITION, content);
if (!parser.matches()) {
@@ -176,7 +183,7 @@ public class StartekProtocolDecoder extends BaseProtocolDecoder {
position.setCourse(parser.nextInt());
position.setAltitude(parser.nextInt());
- position.set(Position.KEY_ODOMETER, parser.nextInt());
+ position.set(Position.KEY_ODOMETER, parser.nextLong());
position.setNetwork(new Network(CellTower.from(
parser.nextInt(), parser.nextInt(), parser.nextHexInt(), parser.nextHexInt(), parser.nextInt())));
@@ -186,6 +193,7 @@ public class StartekProtocolDecoder extends BaseProtocolDecoder {
int input = parser.nextHexInt();
int output = parser.nextHexInt();
position.set(Position.KEY_IGNITION, BitUtil.check(input, 1));
+ position.set(Position.KEY_DOOR, BitUtil.check(input, 2));
position.set(Position.KEY_INPUT, input);
position.set(Position.KEY_OUTPUT, output);
@@ -221,7 +229,7 @@ public class StartekProtocolDecoder extends BaseProtocolDecoder {
}
}
- if (parser.hasNext(6)) {
+ if (parser.hasNextAny(9)) {
position.set(Position.KEY_RPM, parser.nextInt());
position.set(Position.KEY_ENGINE_LOAD, parser.nextInt());
position.set("airFlow", parser.nextInt());
@@ -239,6 +247,87 @@ public class StartekProtocolDecoder extends BaseProtocolDecoder {
position.set(Position.KEY_FUEL_LEVEL, parser.nextInt());
}
+ if (parser.hasNext()) {
+ position.set(Position.KEY_HOURS, parser.nextInt() * 1000L);
+ }
+
+ return position;
+ }
+
+ private Object decodeSerial(DeviceSession deviceSession, String content) {
+
+ Position position = new Position(getProtocolName());
+ position.setDeviceId(deviceSession.getDeviceId());
+
+ getLastLocation(position, null);
+
+ String[] frames = content.split("\r\n");
+
+ for (String frame : frames) {
+ String[] values = frame.split(",");
+ int index = 0;
+ String type = values[index++];
+ switch (type) {
+ case "T1":
+ index += 1; // speed
+ position.set(Position.KEY_RPM, Double.parseDouble(values[index++]));
+ index += 1; // fuel consumption
+ position.set(Position.KEY_FUEL_LEVEL, Double.parseDouble(values[index++]));
+ index += 4; // axel weights
+ index += 1; // turbo pressure
+ position.set(Position.KEY_COOLANT_TEMP, Integer.parseInt(values[index++]));
+ index += 1; // accelerator pedal
+ position.set("torque", Integer.parseInt(values[index++]));
+ index += 1; // firmware version
+ position.set(Position.KEY_POWER, Double.parseDouble(values[index++]));
+ index += 1; // coolant level
+ position.set("oilTemp", Double.parseDouble(values[index++]));
+ index += 1; // oil level
+ position.set(Position.KEY_THROTTLE, Double.parseDouble(values[index++]));
+ index += 1; // air inlet pressure
+ index += 1; // fuel tank secondary
+ index += 1; // current gear
+ index += 1; // seatbelt
+ position.set("oilPressure", Integer.parseInt(values[index++]));
+ index += 1; // wet tank air pressure
+ index += 1; // pto state
+ int ignition = Integer.parseInt(values[index++]);
+ if (ignition < 2) {
+ position.set(Position.KEY_IGNITION, ignition > 0);
+ }
+ index += 1; // brake pedal
+ position.set("catalystLevel", Double.parseDouble(values[index++]));
+ index += 1; // fuel type
+ break;
+ case "T2":
+ position.set(Position.KEY_ODOMETER, Double.parseDouble(values[index++]) * 1000);
+ index += 1; // total fuel
+ index += 1; // fuel used cruise
+ index += 1; // fuel used drive
+ index += 1;
+ index += 1;
+ index += 1; // total idle time
+ index += 1; // total time pto
+ index += 1; // time cruise
+ index += 1;
+ index += 1;
+ index += 1;
+ index += 1;
+ index += 1;
+ index += 1; // brake apps
+ index += 1; // clutch apps
+ position.set(Position.KEY_HOURS, Integer.parseInt(values[index++]));
+ index += 1; // time torque
+ position.set(Position.KEY_FUEL_CONSUMPTION, Double.parseDouble(values[index++]));
+ index += 1; // total cruise control distance
+ position.set(Position.KEY_FUEL_USED, Double.parseDouble(values[index++]));
+ index += 1; // total drive time
+ break;
+ default:
+ break;
+ }
+ }
+
return position;
}
diff --git a/src/main/java/org/traccar/protocol/StbProtocol.java b/src/main/java/org/traccar/protocol/StbProtocol.java
index af4e0d2c4..0beaed39c 100644
--- a/src/main/java/org/traccar/protocol/StbProtocol.java
+++ b/src/main/java/org/traccar/protocol/StbProtocol.java
@@ -22,7 +22,7 @@ import org.traccar.PipelineBuilder;
import org.traccar.TrackerServer;
import org.traccar.config.Config;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class StbProtocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/StbProtocolDecoder.java b/src/main/java/org/traccar/protocol/StbProtocolDecoder.java
index 641359bfd..c52ab485f 100644
--- a/src/main/java/org/traccar/protocol/StbProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/StbProtocolDecoder.java
@@ -22,9 +22,9 @@ import org.traccar.Protocol;
import org.traccar.model.Position;
import org.traccar.session.DeviceSession;
-import javax.json.Json;
-import javax.json.JsonObject;
-import javax.json.JsonValue;
+import jakarta.json.Json;
+import jakarta.json.JsonObject;
+import jakarta.json.JsonValue;
import java.io.StringReader;
import java.net.SocketAddress;
import java.util.Date;
diff --git a/src/main/java/org/traccar/protocol/Stl060Protocol.java b/src/main/java/org/traccar/protocol/Stl060Protocol.java
index 83b5db3bb..ac23ab3ee 100644
--- a/src/main/java/org/traccar/protocol/Stl060Protocol.java
+++ b/src/main/java/org/traccar/protocol/Stl060Protocol.java
@@ -22,7 +22,7 @@ import org.traccar.PipelineBuilder;
import org.traccar.TrackerServer;
import org.traccar.config.Config;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class Stl060Protocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/SuntechProtocol.java b/src/main/java/org/traccar/protocol/SuntechProtocol.java
index 4253b761b..0cc5fc75c 100644
--- a/src/main/java/org/traccar/protocol/SuntechProtocol.java
+++ b/src/main/java/org/traccar/protocol/SuntechProtocol.java
@@ -22,7 +22,7 @@ import org.traccar.TrackerServer;
import org.traccar.config.Config;
import org.traccar.model.Command;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class SuntechProtocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/SuntechProtocolDecoder.java b/src/main/java/org/traccar/protocol/SuntechProtocolDecoder.java
index 047a1822a..53c4a5d02 100644
--- a/src/main/java/org/traccar/protocol/SuntechProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/SuntechProtocolDecoder.java
@@ -271,18 +271,26 @@ public class SuntechProtocolDecoder extends BaseProtocolDecoder {
index += 1; // collaborative network
}
- DateFormat dateFormat = new SimpleDateFormat("yyyyMMddHH:mm:ss");
- dateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
- position.setTime(dateFormat.parse(values[index++] + values[index++]));
+ if (values[index].isEmpty()) {
- position.setLatitude(Double.parseDouble(values[index++]));
- position.setLongitude(Double.parseDouble(values[index++]));
- position.setSpeed(UnitsConverter.knotsFromKph(Double.parseDouble(values[index++])));
- position.setCourse(Double.parseDouble(values[index++]));
+ getLastLocation(position, null);
- position.set(Position.KEY_SATELLITES, Integer.parseInt(values[index++]));
+ } else {
- position.setValid(values[index++].equals("1"));
+ DateFormat dateFormat = new SimpleDateFormat("yyyyMMddHH:mm:ss");
+ dateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
+ position.setTime(dateFormat.parse(values[index++] + values[index++]));
+
+ position.setLatitude(Double.parseDouble(values[index++]));
+ position.setLongitude(Double.parseDouble(values[index++]));
+ position.setSpeed(UnitsConverter.knotsFromKph(Double.parseDouble(values[index++])));
+ position.setCourse(Double.parseDouble(values[index++]));
+
+ position.set(Position.KEY_SATELLITES, Integer.parseInt(values[index++]));
+
+ position.setValid(values[index++].equals("1"));
+
+ }
return position;
}
@@ -446,9 +454,10 @@ public class SuntechProtocolDecoder extends BaseProtocolDecoder {
if (values.length - index >= 2) {
String driverUniqueId = values[index++];
- if (values[index++].equals("1") && !driverUniqueId.isEmpty()) {
+ if (!driverUniqueId.isEmpty()) {
position.set(Position.KEY_DRIVER_UNIQUE_ID, driverUniqueId);
}
+ index += 1; // registered
}
if (isIncludeTemp(deviceSession.getDeviceId())) {
diff --git a/src/main/java/org/traccar/protocol/SupermateProtocol.java b/src/main/java/org/traccar/protocol/SupermateProtocol.java
index 4290b7126..064f12b4b 100644
--- a/src/main/java/org/traccar/protocol/SupermateProtocol.java
+++ b/src/main/java/org/traccar/protocol/SupermateProtocol.java
@@ -23,7 +23,7 @@ import org.traccar.PipelineBuilder;
import org.traccar.TrackerServer;
import org.traccar.config.Config;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class SupermateProtocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/SviasProtocol.java b/src/main/java/org/traccar/protocol/SviasProtocol.java
index 7c6624f7c..a903d503c 100644
--- a/src/main/java/org/traccar/protocol/SviasProtocol.java
+++ b/src/main/java/org/traccar/protocol/SviasProtocol.java
@@ -24,7 +24,7 @@ import org.traccar.TrackerServer;
import org.traccar.config.Config;
import org.traccar.model.Command;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class SviasProtocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/SwiftechProtocol.java b/src/main/java/org/traccar/protocol/SwiftechProtocol.java
index 68cf40d84..d5fa5c5d3 100644
--- a/src/main/java/org/traccar/protocol/SwiftechProtocol.java
+++ b/src/main/java/org/traccar/protocol/SwiftechProtocol.java
@@ -23,7 +23,7 @@ import org.traccar.PipelineBuilder;
import org.traccar.TrackerServer;
import org.traccar.config.Config;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class SwiftechProtocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/T55Protocol.java b/src/main/java/org/traccar/protocol/T55Protocol.java
index cedac275f..e76959fea 100644
--- a/src/main/java/org/traccar/protocol/T55Protocol.java
+++ b/src/main/java/org/traccar/protocol/T55Protocol.java
@@ -23,7 +23,7 @@ import org.traccar.PipelineBuilder;
import org.traccar.TrackerServer;
import org.traccar.config.Config;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class T55Protocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/T55ProtocolDecoder.java b/src/main/java/org/traccar/protocol/T55ProtocolDecoder.java
index 3be161fb8..9e7518ce5 100644
--- a/src/main/java/org/traccar/protocol/T55ProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/T55ProtocolDecoder.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2012 - 2022 Anton Tananaev (anton@traccar.org)
+ * Copyright 2012 - 2023 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.
@@ -41,7 +41,8 @@ public class T55ProtocolDecoder extends BaseProtocolDecoder {
}
private static final Pattern PATTERN_GPRMC = new PatternBuilder()
- .text("$GPRMC,")
+ .text("$")
+ .expression("G[PLN]RMC,")
.number("(dd)(dd)(dd).?d*,") // time (hhmmss)
.expression("([AV]),") // validity
.number("(dd)(dd.d+),") // latitude
@@ -64,7 +65,8 @@ public class T55ProtocolDecoder extends BaseProtocolDecoder {
.compile();
private static final Pattern PATTERN_GPGGA = new PatternBuilder()
- .text("$GPGGA,")
+ .text("$")
+ .expression("G[PLN]GGA,")
.number("(dd)(dd)(dd).?d*,") // time (hhmmss)
.number("(d+)(dd.d+),") // latitude
.expression("([NS]),")
@@ -150,6 +152,18 @@ public class T55ProtocolDecoder extends BaseProtocolDecoder {
.number("xx") // checksum
.compile();
+ private static final Pattern PATTERN_GPTXT = new PatternBuilder()
+ .text("$GPTXT,")
+ .text("NET,")
+ .number("(d+),") // device id
+ .expression("([^,]+),") // network operator
+ .number("(-d+),") // rssi
+ .number("(d+) ") // mcc
+ .number("(d+)") // mnc
+ .text("*")
+ .number("xx") // checksum
+ .compile();
+
private Position position = null;
private Position decodeGprmc(
@@ -328,6 +342,31 @@ public class T55ProtocolDecoder extends BaseProtocolDecoder {
return position;
}
+ private Position decodeGptxt(Channel channel, SocketAddress remoteAddress, String sentence) {
+
+ Parser parser = new Parser(PATTERN_GPTXT, sentence);
+ 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());
+
+ getLastLocation(position, null);
+
+ position.set(Position.KEY_OPERATOR, parser.next());
+ position.set(Position.KEY_RSSI, parser.nextInt());
+ position.set("mcc", parser.nextInt());
+ position.set("mnc", parser.nextInt());
+
+ return position;
+ }
+
private Position decodePubx(Channel channel, SocketAddress remoteAddress, String sentence) {
Parser parser = new Parser(PATTERN_PUBX, sentence);
@@ -407,9 +446,9 @@ public class T55ProtocolDecoder extends BaseProtocolDecoder {
}
} else if (sentence.matches("^[0-9A-F]+$")) {
getDeviceSession(channel, remoteAddress, sentence);
- } else if (sentence.startsWith("$GPRMC")) {
+ } else if (sentence.startsWith("RMC", 3)) {
return decodeGprmc(deviceSession, sentence, remoteAddress, channel);
- } else if (sentence.startsWith("$GPGGA") && deviceSession != null) {
+ } else if (sentence.startsWith("GGA", 3) && deviceSession != null) {
return decodeGpgga(deviceSession, sentence);
} else if (sentence.startsWith("$GPRMA") && deviceSession != null) {
return decodeGprma(deviceSession, sentence);
@@ -421,6 +460,8 @@ public class T55ProtocolDecoder extends BaseProtocolDecoder {
return decodeQze(channel, remoteAddress, sentence);
} else if (sentence.startsWith("$PUBX")) {
return decodePubx(channel, remoteAddress, sentence);
+ } else if (sentence.startsWith("$GPTXT")) {
+ return decodeGptxt(channel, remoteAddress, sentence);
}
return null;
diff --git a/src/main/java/org/traccar/protocol/T57Protocol.java b/src/main/java/org/traccar/protocol/T57Protocol.java
index 4bafe8c6d..e6ef4ccc9 100644
--- a/src/main/java/org/traccar/protocol/T57Protocol.java
+++ b/src/main/java/org/traccar/protocol/T57Protocol.java
@@ -22,7 +22,7 @@ import org.traccar.PipelineBuilder;
import org.traccar.TrackerServer;
import org.traccar.config.Config;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class T57Protocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/T622IridiumProtocol.java b/src/main/java/org/traccar/protocol/T622IridiumProtocol.java
new file mode 100644
index 000000000..22efa38a8
--- /dev/null
+++ b/src/main/java/org/traccar/protocol/T622IridiumProtocol.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2023 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.LengthFieldBasedFrameDecoder;
+import org.traccar.BaseProtocol;
+import org.traccar.PipelineBuilder;
+import org.traccar.TrackerServer;
+import org.traccar.config.Config;
+
+import jakarta.inject.Inject;
+
+public class T622IridiumProtocol extends BaseProtocol {
+
+ @Inject
+ public T622IridiumProtocol(Config config) {
+ addServer(new TrackerServer(config, getName(), false) {
+ @Override
+ protected void addProtocolHandlers(PipelineBuilder pipeline, Config config) {
+ pipeline.addLast(new LengthFieldBasedFrameDecoder(1024, 1, 2));
+ pipeline.addLast(new T622IridiumProtocolDecoder(T622IridiumProtocol.this));
+ }
+ });
+ }
+
+}
diff --git a/src/main/java/org/traccar/protocol/T622IridiumProtocolDecoder.java b/src/main/java/org/traccar/protocol/T622IridiumProtocolDecoder.java
new file mode 100644
index 000000000..9e64ec9be
--- /dev/null
+++ b/src/main/java/org/traccar/protocol/T622IridiumProtocolDecoder.java
@@ -0,0 +1,149 @@
+/*
+ * Copyright 2023 Anton Tananaev (anton@traccar.org)
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.traccar.protocol;
+
+import io.netty.buffer.ByteBuf;
+import io.netty.channel.Channel;
+import org.traccar.BaseProtocolDecoder;
+import org.traccar.Protocol;
+import org.traccar.config.Keys;
+import org.traccar.helper.UnitsConverter;
+import org.traccar.helper.model.AttributeUtil;
+import org.traccar.model.Position;
+import org.traccar.session.DeviceSession;
+
+import java.net.SocketAddress;
+import java.nio.charset.StandardCharsets;
+import java.util.Arrays;
+import java.util.Date;
+import java.util.List;
+import java.util.stream.Collectors;
+
+public class T622IridiumProtocolDecoder extends BaseProtocolDecoder {
+
+ private String format;
+
+ public T622IridiumProtocolDecoder(Protocol protocol) {
+ super(protocol);
+ }
+
+ public List<Integer> getParameters(long deviceId) {
+ String value = AttributeUtil.lookup(
+ getCacheManager(), Keys.PROTOCOL_FORMAT.withPrefix(getProtocolName()), deviceId);
+ return Arrays.stream((value != null ? value : format).split(","))
+ .map(s -> Integer.parseInt(s, 16))
+ .collect(Collectors.toList());
+ }
+
+ public void setFormat(String format) {
+ this.format = format;
+ }
+
+ @Override
+ protected Object decode(
+ Channel channel, SocketAddress remoteAddress, Object msg) throws Exception {
+
+ ByteBuf buf = (ByteBuf) msg;
+
+ buf.readUnsignedByte(); // protocol revision
+ buf.readUnsignedShort(); // length
+ buf.readUnsignedByte(); // header indicator
+ buf.readUnsignedShort(); // header length
+ buf.readUnsignedInt(); // reference
+
+ String imei = buf.readCharSequence(15, StandardCharsets.US_ASCII).toString();
+ DeviceSession deviceSession = getDeviceSession(channel, remoteAddress, imei);
+ if (deviceSession == null) {
+ return null;
+ }
+
+ buf.readUnsignedByte(); // session status
+ buf.readUnsignedShort(); // originator index
+ buf.readUnsignedShort(); // transfer index
+ buf.readUnsignedInt(); // session time
+ buf.readUnsignedByte(); // payload indicator
+ buf.readUnsignedShort(); // payload length
+
+ Position position = new Position(getProtocolName());
+ position.setDeviceId(deviceSession.getDeviceId());
+
+ List<Integer> parameters = getParameters(deviceSession.getDeviceId());
+
+ for (int parameter : parameters) {
+ switch (parameter) {
+ case 0x01:
+ position.set(Position.KEY_EVENT, buf.readUnsignedByte());
+ break;
+ case 0x02:
+ position.setLatitude(buf.readIntLE() / 1000000.0);
+ break;
+ case 0x03:
+ position.setLongitude(buf.readIntLE() / 1000000.0);
+ break;
+ case 0x04:
+ position.setTime(new Date((buf.readUnsignedIntLE() + 946684800) * 1000));
+ break;
+ case 0x05:
+ position.setValid(buf.readUnsignedByte() > 0);
+ break;
+ case 0x06:
+ position.set(Position.KEY_SATELLITES, buf.readUnsignedByte());
+ break;
+ case 0x07:
+ position.set(Position.KEY_RSSI, buf.readUnsignedByte());
+ break;
+ case 0x08:
+ position.setSpeed(UnitsConverter.knotsFromKph(buf.readUnsignedShortLE()));
+ break;
+ case 0x09:
+ position.setCourse(buf.readUnsignedShortLE());
+ break;
+ case 0x0A:
+ position.set(Position.KEY_HDOP, buf.readUnsignedByte() * 0.1);
+ break;
+ case 0x0B:
+ position.setAltitude(buf.readShortLE());
+ break;
+ case 0x0C:
+ position.set(Position.KEY_ODOMETER, buf.readUnsignedIntLE());
+ break;
+ case 0x0D:
+ position.set(Position.KEY_HOURS, buf.readUnsignedIntLE() * 1000);
+ break;
+ case 0x14:
+ position.set(Position.KEY_OUTPUT, buf.readUnsignedByte());
+ break;
+ case 0x15:
+ position.set(Position.KEY_INPUT, buf.readUnsignedByte());
+ break;
+ case 0x19:
+ position.set(Position.KEY_BATTERY, buf.readUnsignedShortLE() * 0.01);
+ break;
+ case 0x1A:
+ position.set(Position.KEY_POWER, buf.readUnsignedShortLE() * 0.01);
+ break;
+ case 0x1B:
+ buf.readUnsignedByte(); // geofence
+ break;
+ default:
+ break;
+ }
+ }
+
+ return position;
+ }
+
+}
diff --git a/src/main/java/org/traccar/protocol/T800xProtocol.java b/src/main/java/org/traccar/protocol/T800xProtocol.java
index 253c3cb73..f50f22a18 100644
--- a/src/main/java/org/traccar/protocol/T800xProtocol.java
+++ b/src/main/java/org/traccar/protocol/T800xProtocol.java
@@ -22,7 +22,7 @@ import org.traccar.TrackerServer;
import org.traccar.config.Config;
import org.traccar.model.Command;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class T800xProtocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/T800xProtocolDecoder.java b/src/main/java/org/traccar/protocol/T800xProtocolDecoder.java
index 6e09e6e3b..23750be8d 100644
--- a/src/main/java/org/traccar/protocol/T800xProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/T800xProtocolDecoder.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2015 - 2021 Anton Tananaev (anton@traccar.org)
+ * Copyright 2015 - 2023 Anton Tananaev (anton@traccar.org)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -20,6 +20,8 @@ import io.netty.buffer.ByteBufUtil;
import io.netty.buffer.Unpooled;
import io.netty.channel.Channel;
import org.traccar.BaseProtocolDecoder;
+import org.traccar.config.Keys;
+import org.traccar.helper.model.AttributeUtil;
import org.traccar.session.DeviceSession;
import org.traccar.NetworkMessage;
import org.traccar.Protocol;
@@ -161,7 +163,7 @@ public class T800xProtocolDecoder extends BaseProtocolDecoder {
boolean positionType = type == MSG_GPS || type == MSG_GPS_2 || type == MSG_ALARM || type == MSG_ALARM_2;
if (!positionType) {
- sendResponse(channel, header, type, index, imei, 0);
+ sendResponse(channel, header, type, header == 0x2323 ? 1 : index, imei, 0);
}
if (positionType) {
@@ -389,7 +391,7 @@ public class T800xProtocolDecoder extends BaseProtocolDecoder {
for (int i = 1; i <= adcCount; i++) {
String value = ByteBufUtil.hexDump(buf.readSlice(2));
if (!value.equals("ffff")) {
- position.set(Position.PREFIX_ADC + i, Integer.parseInt(value) * 0.01);
+ position.set(Position.PREFIX_ADC + i, Integer.parseInt(value, 16) * 0.01);
}
}
}
@@ -398,6 +400,7 @@ public class T800xProtocolDecoder extends BaseProtocolDecoder {
int alarm = buf.readUnsignedByte();
position.set(Position.KEY_ALARM, header != 0x2727 ? decodeAlarm1(alarm) : decodeAlarm2(alarm));
+ position.set("alarmCode", alarm);
if (header != 0x2727) {
@@ -468,6 +471,7 @@ public class T800xProtocolDecoder extends BaseProtocolDecoder {
int inputStatus = buf.readUnsignedShort();
position.set(Position.KEY_IGNITION, BitUtil.check(inputStatus, 2));
position.set(Position.KEY_RSSI, BitUtil.between(inputStatus, 4, 11));
+ position.set(Position.KEY_INPUT, inputStatus);
buf.readUnsignedShort(); // ignition on upload interval
buf.readUnsignedInt(); // ignition off upload interval
@@ -511,8 +515,10 @@ public class T800xProtocolDecoder extends BaseProtocolDecoder {
}
}
- if (type == MSG_ALARM || type == MSG_ALARM_2) {
- sendResponse(channel, header, type, index, imei, alarm);
+ boolean acknowledgement = AttributeUtil.lookup(
+ getCacheManager(), Keys.PROTOCOL_ACK.withPrefix(getProtocolName()), deviceSession.getDeviceId());
+ if (acknowledgement || type == MSG_ALARM || type == MSG_ALARM_2) {
+ sendResponse(channel, header, type, header == 0x2323 ? 1 : index, imei, alarm);
}
return position;
diff --git a/src/main/java/org/traccar/protocol/TaipPrefixEncoder.java b/src/main/java/org/traccar/protocol/TaipPrefixEncoder.java
index 48419af2a..75fd447d0 100644
--- a/src/main/java/org/traccar/protocol/TaipPrefixEncoder.java
+++ b/src/main/java/org/traccar/protocol/TaipPrefixEncoder.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2021 - 2022 Anton Tananaev (anton@traccar.org)
+ * Copyright 2021 - 2023 Anton Tananaev (anton@traccar.org)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -15,40 +15,20 @@
*/
package org.traccar.protocol;
-import com.google.inject.Inject;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToMessageEncoder;
-import org.traccar.Protocol;
-import org.traccar.config.Config;
-import org.traccar.config.Keys;
import java.util.List;
@ChannelHandler.Sharable
public class TaipPrefixEncoder extends MessageToMessageEncoder<ByteBuf> {
- private final Protocol protocol;
- private Config config;
-
- public TaipPrefixEncoder(Protocol protocol) {
- this.protocol = protocol;
- }
-
- @Inject
- public void setConfig(Config config) {
- this.config = config;
- }
-
@Override
protected void encode(ChannelHandlerContext ctx, ByteBuf msg, List<Object> out) {
- if (config.getBoolean(Keys.PROTOCOL_PREFIX.withPrefix(protocol.getName()))) {
- out.add(Unpooled.wrappedBuffer(Unpooled.wrappedBuffer(new byte[] {0x20, 0x20, 0x06, 0x00}), msg.retain()));
- } else {
- out.add(msg.retain());
- }
+ out.add(Unpooled.wrappedBuffer(Unpooled.wrappedBuffer(new byte[] {0x20, 0x20, 0x06, 0x00}), msg.retain()));
}
}
diff --git a/src/main/java/org/traccar/protocol/TaipProtocol.java b/src/main/java/org/traccar/protocol/TaipProtocol.java
index 943ec98c5..f57bb296c 100644
--- a/src/main/java/org/traccar/protocol/TaipProtocol.java
+++ b/src/main/java/org/traccar/protocol/TaipProtocol.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2015 - 2021 Anton Tananaev (anton@traccar.org)
+ * Copyright 2015 - 2023 Anton Tananaev (anton@traccar.org)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -23,7 +23,8 @@ import org.traccar.PipelineBuilder;
import org.traccar.TrackerServer;
import org.traccar.config.Config;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
+import org.traccar.config.Keys;
public class TaipProtocol extends BaseProtocol {
@@ -33,7 +34,9 @@ public class TaipProtocol extends BaseProtocol {
@Override
protected void addProtocolHandlers(PipelineBuilder pipeline, Config config) {
pipeline.addLast(new CharacterDelimiterFrameDecoder(1024, '<'));
- pipeline.addLast(new TaipPrefixEncoder(TaipProtocol.this));
+ if (config.getBoolean(Keys.PROTOCOL_PREFIX.withPrefix(getName()))) {
+ pipeline.addLast(new TaipPrefixEncoder());
+ }
pipeline.addLast(new StringDecoder());
pipeline.addLast(new StringEncoder());
pipeline.addLast(new TaipProtocolDecoder(TaipProtocol.this));
@@ -42,7 +45,9 @@ public class TaipProtocol extends BaseProtocol {
addServer(new TrackerServer(config, getName(), true) {
@Override
protected void addProtocolHandlers(PipelineBuilder pipeline, Config config) {
- pipeline.addLast(new TaipPrefixEncoder(TaipProtocol.this));
+ if (config.getBoolean(Keys.PROTOCOL_PREFIX.withPrefix(getName()))) {
+ pipeline.addLast(new TaipPrefixEncoder());
+ }
pipeline.addLast(new StringDecoder());
pipeline.addLast(new StringEncoder());
pipeline.addLast(new TaipProtocolDecoder(TaipProtocol.this));
diff --git a/src/main/java/org/traccar/protocol/TaipProtocolDecoder.java b/src/main/java/org/traccar/protocol/TaipProtocolDecoder.java
index e5e84b7c4..448d7ffca 100644
--- a/src/main/java/org/traccar/protocol/TaipProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/TaipProtocolDecoder.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2013 - 2021 Anton Tananaev (anton@traccar.org)
+ * Copyright 2013 - 2023 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.
@@ -26,7 +26,6 @@ import org.traccar.helper.DateBuilder;
import org.traccar.helper.DateUtil;
import org.traccar.helper.Parser;
import org.traccar.helper.PatternBuilder;
-import org.traccar.helper.UnitsConverter;
import org.traccar.model.Position;
import java.net.SocketAddress;
@@ -49,7 +48,7 @@ public class TaipProtocolDecoder extends BaseProtocolDecoder {
.groupEnd("?")
.number("(d{5})") // seconds
.or()
- .expression("(?:RGP|RCQ|RCV|RBR|RUS00),?") // type
+ .expression("(?:RGP|RCQ|RCV|RBR|RUS00|RPI),?") // type
.number("(dd)?") // event
.number("(dd)(dd)(dd)") // date (mmddyy)
.number("(dd)(dd)(dd)") // time (hhmmss)
@@ -84,7 +83,7 @@ public class TaipProtocolDecoder extends BaseProtocolDecoder {
.or()
.groupBegin()
.number("(xx)") // input
- .number("(xx)") // satellites
+ .number("xx") // satellites / outputs
.number("(ddd)") // battery
.number("(x{8})") // odometer
.number("[01]") // gps power
@@ -96,12 +95,14 @@ public class TaipProtocolDecoder extends BaseProtocolDecoder {
.number("[01]") // modem power
.number("[0-5]") // gsm status
.number("(dd)") // rssi
+ .groupBegin()
.number("([-+]dddd)") // temperature 1
.number("xx") // seconds from last
.number("([-+]dddd)") // temperature 2
.number("xx") // seconds from last
.groupEnd("?")
.groupEnd("?")
+ .groupEnd("?")
.groupEnd()
.any()
.compile();
@@ -192,7 +193,7 @@ public class TaipProtocolDecoder extends BaseProtocolDecoder {
position.setLongitude(parser.nextCoordinate(Parser.CoordinateFormat.HEM_DEG_MIN));
}
- position.setSpeed(UnitsConverter.knotsFromMph(parser.nextDouble(0)));
+ position.setSpeed(convertSpeed(parser.nextDouble(0), "mph"));
position.setCourse(parser.nextDouble(0));
if (parser.hasNext(2)) {
@@ -217,17 +218,18 @@ public class TaipProtocolDecoder extends BaseProtocolDecoder {
position.set(Position.KEY_HDOP, parser.nextInt());
}
- if (parser.hasNext(4)) {
+ if (parser.hasNext(3)) {
position.set(Position.KEY_INPUT, parser.nextHexInt(0));
- position.set(Position.KEY_SATELLITES, parser.nextHexInt(0));
position.set(Position.KEY_BATTERY, parser.nextInt(0));
position.set(Position.KEY_ODOMETER, parser.nextLong(16, 0));
}
- if (parser.hasNext(4)) {
+ if (parser.hasNext(3)) {
valid = parser.nextInt() > 0;
position.set(Position.KEY_PDOP, parser.nextInt());
position.set(Position.KEY_RSSI, parser.nextInt());
+ }
+ if (parser.hasNext(2)) {
position.set(Position.PREFIX_TEMP + 1, parser.nextInt() * 0.01);
position.set(Position.PREFIX_TEMP + 2, parser.nextInt() * 0.01);
}
@@ -262,6 +264,7 @@ public class TaipProtocolDecoder extends BaseProtocolDecoder {
String uniqueId = null;
DeviceSession deviceSession = null;
String messageIndex = null;
+ boolean indexFirst = true;
if (attributes != null) {
for (String attribute : attributes) {
@@ -276,6 +279,9 @@ public class TaipProtocolDecoder extends BaseProtocolDecoder {
if (deviceSession != null) {
position.setDeviceId(deviceSession.getDeviceId());
}
+ if (messageIndex == null) {
+ indexFirst = false;
+ }
break;
case "io":
position.set(Position.KEY_IGNITION, BitUtil.check(value.charAt(0) - '0', 0));
@@ -315,7 +321,11 @@ public class TaipProtocolDecoder extends BaseProtocolDecoder {
if (messageIndex.startsWith("#IP")) {
response = ">SAK;ID=" + uniqueId + ";" + messageIndex + "<";
} else {
- response = ">ACK;ID=" + uniqueId + ";" + messageIndex + ";*";
+ if (indexFirst) {
+ response = ">ACK;" + messageIndex + ";ID=" + uniqueId + ";*";
+ } else {
+ response = ">ACK;ID=" + uniqueId + ";" + messageIndex + ";*";
+ }
response += String.format("%02X", Checksum.xor(response)) + "<";
}
channel.writeAndFlush(new NetworkMessage(response, remoteAddress));
diff --git a/src/main/java/org/traccar/protocol/TechTltProtocol.java b/src/main/java/org/traccar/protocol/TechTltProtocol.java
index 191dd9ccc..a4a7460b0 100644
--- a/src/main/java/org/traccar/protocol/TechTltProtocol.java
+++ b/src/main/java/org/traccar/protocol/TechTltProtocol.java
@@ -22,7 +22,7 @@ import org.traccar.PipelineBuilder;
import org.traccar.TrackerServer;
import org.traccar.config.Config;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class TechTltProtocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/TechtoCruzProtocol.java b/src/main/java/org/traccar/protocol/TechtoCruzProtocol.java
index 265a3eb64..f0828a99e 100644
--- a/src/main/java/org/traccar/protocol/TechtoCruzProtocol.java
+++ b/src/main/java/org/traccar/protocol/TechtoCruzProtocol.java
@@ -22,7 +22,7 @@ import org.traccar.PipelineBuilder;
import org.traccar.TrackerServer;
import org.traccar.config.Config;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class TechtoCruzProtocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/TekProtocol.java b/src/main/java/org/traccar/protocol/TekProtocol.java
index 54e860d79..56714041b 100644
--- a/src/main/java/org/traccar/protocol/TekProtocol.java
+++ b/src/main/java/org/traccar/protocol/TekProtocol.java
@@ -20,7 +20,7 @@ import org.traccar.PipelineBuilder;
import org.traccar.TrackerServer;
import org.traccar.config.Config;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class TekProtocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/TelemaxProtocol.java b/src/main/java/org/traccar/protocol/TelemaxProtocol.java
index 9e9cbb50e..792a5b176 100644
--- a/src/main/java/org/traccar/protocol/TelemaxProtocol.java
+++ b/src/main/java/org/traccar/protocol/TelemaxProtocol.java
@@ -23,7 +23,7 @@ import org.traccar.PipelineBuilder;
import org.traccar.TrackerServer;
import org.traccar.config.Config;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class TelemaxProtocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/TelicProtocol.java b/src/main/java/org/traccar/protocol/TelicProtocol.java
index 9ef7864ca..fc5bdf0d1 100644
--- a/src/main/java/org/traccar/protocol/TelicProtocol.java
+++ b/src/main/java/org/traccar/protocol/TelicProtocol.java
@@ -22,7 +22,7 @@ import org.traccar.PipelineBuilder;
import org.traccar.TrackerServer;
import org.traccar.config.Config;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class TelicProtocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/TeltonikaFrameDecoder.java b/src/main/java/org/traccar/protocol/TeltonikaFrameDecoder.java
index 3a0962584..aabc24887 100644
--- a/src/main/java/org/traccar/protocol/TeltonikaFrameDecoder.java
+++ b/src/main/java/org/traccar/protocol/TeltonikaFrameDecoder.java
@@ -29,7 +29,7 @@ public class TeltonikaFrameDecoder extends BaseFrameDecoder {
protected Object decode(
ChannelHandlerContext ctx, Channel channel, ByteBuf buf) throws Exception {
- while (buf.isReadable() && buf.getByte(buf.readerIndex()) == (byte) 0xff) {
+ if (buf.isReadable() && buf.getByte(buf.readerIndex()) == (byte) 0xff) {
return buf.readRetainedSlice(1);
}
diff --git a/src/main/java/org/traccar/protocol/TeltonikaProtocol.java b/src/main/java/org/traccar/protocol/TeltonikaProtocol.java
index 38283cb64..f2d610251 100644
--- a/src/main/java/org/traccar/protocol/TeltonikaProtocol.java
+++ b/src/main/java/org/traccar/protocol/TeltonikaProtocol.java
@@ -21,7 +21,7 @@ import org.traccar.TrackerServer;
import org.traccar.config.Config;
import org.traccar.model.Command;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class TeltonikaProtocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/TeltonikaProtocolDecoder.java b/src/main/java/org/traccar/protocol/TeltonikaProtocolDecoder.java
index 929eca8aa..6197c6c13 100644
--- a/src/main/java/org/traccar/protocol/TeltonikaProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/TeltonikaProtocolDecoder.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2013 - 2022 Anton Tananaev (anton@traccar.org)
+ * Copyright 2013 - 2023 Anton Tananaev (anton@traccar.org)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -20,7 +20,7 @@ import io.netty.buffer.ByteBufUtil;
import io.netty.buffer.Unpooled;
import io.netty.channel.Channel;
import org.traccar.BaseProtocolDecoder;
-import org.traccar.model.Device;
+import org.traccar.helper.BufferUtil;
import org.traccar.session.DeviceSession;
import org.traccar.NetworkMessage;
import org.traccar.Protocol;
@@ -33,6 +33,7 @@ import org.traccar.model.Network;
import org.traccar.model.Position;
import java.net.SocketAddress;
+import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
import java.util.Date;
import java.util.HashMap;
@@ -112,18 +113,6 @@ public class TeltonikaProtocolDecoder extends BaseProtocolDecoder {
}
}
- private boolean isPrintable(ByteBuf buf, int length) {
- boolean printable = true;
- for (int i = 0; i < length; i++) {
- byte b = buf.getByte(buf.readerIndex() + i);
- if (b < 32 && b != '\r' && b != '\n') {
- printable = false;
- break;
- }
- }
- return printable;
- }
-
private void decodeSerial(
Channel channel, SocketAddress remoteAddress, DeviceSession deviceSession, Position position, ByteBuf buf) {
@@ -169,7 +158,7 @@ public class TeltonikaProtocolDecoder extends BaseProtocolDecoder {
position.set(Position.KEY_TYPE, type);
int length = buf.readInt();
- if (isPrintable(buf, length)) {
+ if (BufferUtil.isPrintable(buf, length)) {
String data = buf.readSlice(length).toString(StandardCharsets.US_ASCII).trim();
if (data.startsWith("UUUUww") && data.endsWith("SSS")) {
String[] values = data.substring(6, data.length() - 4).split(";");
@@ -231,6 +220,8 @@ public class TeltonikaProtocolDecoder extends BaseProtocolDecoder {
register(26, null, (p, b) -> p.set("bleTemp2", b.readShort() * 0.01));
register(27, null, (p, b) -> p.set("bleTemp3", b.readShort() * 0.01));
register(28, null, (p, b) -> p.set("bleTemp4", b.readShort() * 0.01));
+ register(30, fmbXXX, (p, b) -> p.set("faultCount", b.readUnsignedByte()));
+ register(32, fmbXXX, (p, b) -> p.set(Position.KEY_COOLANT_TEMP, b.readByte()));
register(66, null, (p, b) -> p.set(Position.KEY_POWER, b.readUnsignedShort() * 0.001));
register(67, null, (p, b) -> p.set(Position.KEY_BATTERY, b.readUnsignedShort() * 0.001));
register(68, fmbXXX, (p, b) -> p.set("batteryCurrent", b.readUnsignedShort() * 0.001));
@@ -239,28 +230,52 @@ public class TeltonikaProtocolDecoder extends BaseProtocolDecoder {
register(74, fmbXXX, (p, b) -> p.set(Position.PREFIX_TEMP + 3, b.readInt() * 0.1));
register(75, fmbXXX, (p, b) -> p.set(Position.PREFIX_TEMP + 4, b.readInt() * 0.1));
register(78, null, (p, b) -> {
- long driverUniqueId = b.readLong();
+ long driverUniqueId = b.readLongLE();
if (driverUniqueId > 0) {
p.set(Position.KEY_DRIVER_UNIQUE_ID, String.format("%016X", driverUniqueId));
}
});
register(80, fmbXXX, (p, b) -> p.set("dataMode", b.readUnsignedByte()));
+ register(81, fmbXXX, (p, b) -> p.set(Position.KEY_OBD_SPEED, b.readUnsignedByte()));
+ register(82, fmbXXX, (p, b) -> p.set(Position.KEY_THROTTLE, b.readUnsignedByte()));
+ register(83, fmbXXX, (p, b) -> p.set(Position.KEY_FUEL_USED, b.readUnsignedInt() * 0.1));
+ register(84, fmbXXX, (p, b) -> p.set(Position.KEY_FUEL_LEVEL, b.readUnsignedShort() * 0.1));
+ register(85, fmbXXX, (p, b) -> p.set(Position.KEY_RPM, b.readUnsignedShort()));
+ register(87, fmbXXX, (p, b) -> p.set(Position.KEY_OBD_ODOMETER, b.readUnsignedInt()));
+ register(89, fmbXXX, (p, b) -> p.set("fuelLevelPercentage", b.readUnsignedByte()));
register(90, null, (p, b) -> p.set(Position.KEY_DOOR, b.readUnsignedShort()));
- register(115, fmbXXX, (p, b) -> p.set(Position.KEY_COOLANT_TEMP, b.readShort() * 0.1));
+ register(110, fmbXXX, (p, b) -> p.set(Position.KEY_FUEL_CONSUMPTION, b.readUnsignedShort() * 0.1));
+ register(113, fmbXXX, (p, b) -> p.set(Position.KEY_BATTERY_LEVEL, b.readUnsignedByte()));
register(179, null, (p, b) -> p.set(Position.PREFIX_OUT + 1, b.readUnsignedByte() > 0));
register(180, null, (p, b) -> p.set(Position.PREFIX_OUT + 2, b.readUnsignedByte() > 0));
register(181, null, (p, b) -> p.set(Position.KEY_PDOP, b.readUnsignedShort() * 0.1));
register(182, null, (p, b) -> p.set(Position.KEY_HDOP, b.readUnsignedShort() * 0.1));
register(199, null, (p, b) -> p.set(Position.KEY_ODOMETER_TRIP, b.readUnsignedInt()));
register(200, fmbXXX, (p, b) -> p.set("sleepMode", b.readUnsignedByte()));
- register(205, fmbXXX, (p, b) -> p.set("cid", b.readUnsignedShort()));
+ register(205, fmbXXX, (p, b) -> p.set("cid2g", b.readUnsignedShort()));
register(206, fmbXXX, (p, b) -> p.set("lac", b.readUnsignedShort()));
+ register(232, fmbXXX, (p, b) -> p.set("cngStatus", b.readUnsignedByte() > 0));
+ register(233, fmbXXX, (p, b) -> p.set("cngUsed", b.readUnsignedInt() * 0.1));
+ register(234, fmbXXX, (p, b) -> p.set("cngLevel", b.readUnsignedShort()));
+ register(235, fmbXXX, (p, b) -> p.set("oilLevel", b.readUnsignedByte()));
register(236, null, (p, b) -> {
p.set(Position.KEY_ALARM, b.readUnsignedByte() > 0 ? Position.ALARM_GENERAL : null);
});
register(239, null, (p, b) -> p.set(Position.KEY_IGNITION, b.readUnsignedByte() > 0));
register(240, null, (p, b) -> p.set(Position.KEY_MOTION, b.readUnsignedByte() > 0));
register(241, null, (p, b) -> p.set(Position.KEY_OPERATOR, b.readUnsignedInt()));
+ register(246, fmbXXX, (p, b) -> {
+ p.set(Position.KEY_ALARM, b.readUnsignedByte() > 0 ? Position.ALARM_TOW : null);
+ });
+ register(247, fmbXXX, (p, b) -> {
+ p.set(Position.KEY_ALARM, b.readUnsignedByte() > 0 ? Position.ALARM_ACCIDENT : null);
+ });
+ register(249, fmbXXX, (p, b) -> {
+ p.set(Position.KEY_ALARM, b.readUnsignedByte() > 0 ? Position.ALARM_JAMMING : null);
+ });
+ register(252, fmbXXX, (p, b) -> {
+ p.set(Position.KEY_ALARM, b.readUnsignedByte() > 0 ? Position.ALARM_POWER_CUT : null);
+ });
register(253, null, (p, b) -> {
switch (b.readUnsignedByte()) {
case 1:
@@ -276,6 +291,7 @@ public class TeltonikaProtocolDecoder extends BaseProtocolDecoder {
break;
}
});
+ register(636, fmbXXX, (p, b) -> p.set("cid4g", b.readUnsignedInt()));
}
private void decodeGh3000Parameter(Position position, int id, ByteBuf buf, int length) {
@@ -366,14 +382,23 @@ public class TeltonikaProtocolDecoder extends BaseProtocolDecoder {
position.setNetwork(network);
}
} else {
- Integer cid = (Integer) position.getAttributes().remove("cid");
+ Integer cid2g = (Integer) position.getAttributes().remove("cid2g");
+ Long cid4g = (Long) position.getAttributes().remove("cid4g");
Integer lac = (Integer) position.getAttributes().remove("lac");
- if (cid != null && lac != null) {
- CellTower cellTower = CellTower.fromLacCid(getConfig(), lac, cid);
+ if (lac != null && (cid2g != null || cid4g != null)) {
+ Network network = new Network();
+ CellTower cellTower;
+ if (cid2g != null) {
+ cellTower = CellTower.fromLacCid(getConfig(), lac, cid2g);
+ } else {
+ cellTower = CellTower.fromLacCid(getConfig(), lac, cid4g);
+ network.setRadioType("lte");
+ }
long operator = position.getInteger(Position.KEY_OPERATOR);
if (operator >= 1000) {
cellTower.setOperator(operator);
}
+ network.addCellTower(cellTower);
position.setNetwork(new Network(cellTower));
}
}
@@ -563,6 +588,38 @@ public class TeltonikaProtocolDecoder extends BaseProtocolDecoder {
}
index += 1;
}
+ } else if (id == 548 || id == 10829 || id == 10831) {
+ ByteBuf data = buf.readSlice(length);
+ data.readUnsignedByte(); // header
+ for (int i = 1; data.isReadable(); i++) {
+ ByteBuf beacon = data.readSlice(data.readUnsignedByte());
+ while (beacon.isReadable()) {
+ int parameterId = beacon.readUnsignedByte();
+ int parameterLength = beacon.readUnsignedByte();
+ switch (parameterId) {
+ case 0:
+ position.set("tag" + i + "Rssi", (int) beacon.readByte());
+ break;
+ case 1:
+ String beaconId = ByteBufUtil.hexDump(beacon.readSlice(parameterLength));
+ position.set("tag" + i + "Id", beaconId);
+ break;
+ case 2:
+ String beaconData = ByteBufUtil.hexDump(beacon.readSlice(parameterLength));
+ position.set("tag" + i + "Data", beaconData);
+ break;
+ case 13:
+ position.set("tag" + i + "LowBattery", beacon.readUnsignedByte());
+ break;
+ case 14:
+ position.set("tag" + i + "Battery", beacon.readUnsignedShort());
+ break;
+ default:
+ beacon.skipBytes(parameterLength);
+ break;
+ }
+ }
+ }
} else {
position.set(Position.PREFIX_IO + id, ByteBufUtil.hexDump(buf.readSlice(length)));
}
@@ -571,6 +628,14 @@ public class TeltonikaProtocolDecoder extends BaseProtocolDecoder {
decodeNetwork(position, model);
+ if (model != null && model.matches("FM.6..")) {
+ Long driverMsb = (Long) position.getAttributes().get("io195");
+ Long driverLsb = (Long) position.getAttributes().get("io196");
+ if (driverMsb != null && driverLsb != null) {
+ String driver = new String(ByteBuffer.allocate(16).putLong(driverMsb).putLong(driverLsb).array());
+ position.set(Position.KEY_DRIVER_UNIQUE_ID, driver);
+ }
+ }
}
private List<Position> parseData(
@@ -588,7 +653,6 @@ public class TeltonikaProtocolDecoder extends BaseProtocolDecoder {
if (deviceSession == null) {
return null;
}
- String model = getCacheManager().getObject(Device.class, deviceSession.getDeviceId()).getModel();
for (int i = 0; i < count; i++) {
Position position = new Position(getProtocolName());
@@ -600,9 +664,13 @@ public class TeltonikaProtocolDecoder extends BaseProtocolDecoder {
buf.readUnsignedByte(); // type
int length = buf.readInt() - 4;
getLastLocation(position, new Date(buf.readUnsignedInt() * 1000));
- if (isPrintable(buf, length)) {
- position.set(Position.KEY_RESULT,
- buf.readCharSequence(length, StandardCharsets.US_ASCII).toString().trim());
+ if (BufferUtil.isPrintable(buf, length)) {
+ String data = buf.readCharSequence(length, StandardCharsets.US_ASCII).toString().trim();
+ if (data.startsWith("GTSL")) {
+ position.set(Position.KEY_DRIVER_UNIQUE_ID, data.split("\\|")[4]);
+ } else {
+ position.set(Position.KEY_RESULT, data);
+ }
} else {
position.set(Position.KEY_RESULT,
ByteBufUtil.hexDump(buf.readSlice(length)));
@@ -610,7 +678,7 @@ public class TeltonikaProtocolDecoder extends BaseProtocolDecoder {
} else if (codec == CODEC_12) {
decodeSerial(channel, remoteAddress, deviceSession, position, buf);
} else {
- decodeLocation(position, buf, codec, model);
+ decodeLocation(position, buf, codec, getDeviceModel(deviceSession));
}
if (!position.getOutdated() || !position.getAttributes().isEmpty()) {
diff --git a/src/main/java/org/traccar/protocol/TeraTrackProtocol.java b/src/main/java/org/traccar/protocol/TeraTrackProtocol.java
index 73219cc5e..e872ddf42 100644
--- a/src/main/java/org/traccar/protocol/TeraTrackProtocol.java
+++ b/src/main/java/org/traccar/protocol/TeraTrackProtocol.java
@@ -22,7 +22,7 @@ import org.traccar.PipelineBuilder;
import org.traccar.TrackerServer;
import org.traccar.config.Config;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class TeraTrackProtocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/TeraTrackProtocolDecoder.java b/src/main/java/org/traccar/protocol/TeraTrackProtocolDecoder.java
index 313210f63..be4b98e4c 100644
--- a/src/main/java/org/traccar/protocol/TeraTrackProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/TeraTrackProtocolDecoder.java
@@ -23,8 +23,8 @@ import org.traccar.Protocol;
import org.traccar.helper.UnitsConverter;
import org.traccar.model.Position;
-import javax.json.Json;
-import javax.json.JsonObject;
+import jakarta.json.Json;
+import jakarta.json.JsonObject;
import java.io.StringReader;
import java.net.SocketAddress;
import java.text.DateFormat;
@@ -63,7 +63,7 @@ public class TeraTrackProtocolDecoder extends BaseProtocolDecoder {
position.setSpeed(UnitsConverter.knotsFromKph(Integer.parseInt(json.getString("Speed"))));
position.set(Position.KEY_ODOMETER, Integer.parseInt(json.getString("Mileage")));
- position.set(Position.KEY_BLOCKED, json.getString("LockOpen").equals("0"));
+ position.set(Position.KEY_LOCK, json.getString("LockOpen").equals("0"));
position.set(Position.KEY_DRIVER_UNIQUE_ID, json.getString("CardNo"));
position.set(Position.KEY_ALARM, json.getString("LowPower").equals("1") ? Position.ALARM_LOW_POWER : null);
position.set(Position.KEY_BATTERY_LEVEL, Integer.parseInt(json.getString("Power")));
diff --git a/src/main/java/org/traccar/protocol/ThinkPowerProtocol.java b/src/main/java/org/traccar/protocol/ThinkPowerProtocol.java
index 38bf078aa..b23dadf08 100644
--- a/src/main/java/org/traccar/protocol/ThinkPowerProtocol.java
+++ b/src/main/java/org/traccar/protocol/ThinkPowerProtocol.java
@@ -21,7 +21,7 @@ import org.traccar.PipelineBuilder;
import org.traccar.TrackerServer;
import org.traccar.config.Config;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class ThinkPowerProtocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/ThinkRaceProtocol.java b/src/main/java/org/traccar/protocol/ThinkRaceProtocol.java
index 782b0a352..34b80ba87 100644
--- a/src/main/java/org/traccar/protocol/ThinkRaceProtocol.java
+++ b/src/main/java/org/traccar/protocol/ThinkRaceProtocol.java
@@ -21,7 +21,7 @@ import org.traccar.PipelineBuilder;
import org.traccar.TrackerServer;
import org.traccar.config.Config;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class ThinkRaceProtocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/ThurayaProtocol.java b/src/main/java/org/traccar/protocol/ThurayaProtocol.java
index f709a1183..33d486f6b 100644
--- a/src/main/java/org/traccar/protocol/ThurayaProtocol.java
+++ b/src/main/java/org/traccar/protocol/ThurayaProtocol.java
@@ -21,7 +21,7 @@ import org.traccar.PipelineBuilder;
import org.traccar.TrackerServer;
import org.traccar.config.Config;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class ThurayaProtocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/Tk102Protocol.java b/src/main/java/org/traccar/protocol/Tk102Protocol.java
index 150e83ab3..b6a82981b 100644
--- a/src/main/java/org/traccar/protocol/Tk102Protocol.java
+++ b/src/main/java/org/traccar/protocol/Tk102Protocol.java
@@ -21,7 +21,7 @@ import org.traccar.PipelineBuilder;
import org.traccar.TrackerServer;
import org.traccar.config.Config;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class Tk102Protocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/Tk103Protocol.java b/src/main/java/org/traccar/protocol/Tk103Protocol.java
index cf09886f5..b641ef083 100644
--- a/src/main/java/org/traccar/protocol/Tk103Protocol.java
+++ b/src/main/java/org/traccar/protocol/Tk103Protocol.java
@@ -24,7 +24,7 @@ import org.traccar.TrackerServer;
import org.traccar.config.Config;
import org.traccar.model.Command;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class Tk103Protocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/Tk103ProtocolDecoder.java b/src/main/java/org/traccar/protocol/Tk103ProtocolDecoder.java
index b343c3b33..6c926da90 100644
--- a/src/main/java/org/traccar/protocol/Tk103ProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/Tk103ProtocolDecoder.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2012 - 2022 Anton Tananaev (anton@traccar.org)
+ * Copyright 2012 - 2023 Anton Tananaev (anton@traccar.org)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -15,8 +15,11 @@
*/
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.helper.DataConverter;
import org.traccar.session.DeviceSession;
import org.traccar.NetworkMessage;
import org.traccar.Protocol;
@@ -448,6 +451,106 @@ public class Tk103ProtocolDecoder extends BaseProtocolDecoder {
return position;
}
+ private Position decodeBms(Channel channel, SocketAddress remoteAddress, String sentence) {
+ String id = sentence.substring(1, 13);
+ DeviceSession deviceSession = getDeviceSession(channel, remoteAddress, id);
+ if (deviceSession == null) {
+ return null;
+ }
+
+ Position position = new Position(getProtocolName());
+ position.setDeviceId(deviceSession.getDeviceId());
+
+ getLastLocation(position, null);
+
+ String payload = sentence.substring(1 + 12 + 4, sentence.length() - 1);
+
+ if (sentence.startsWith("BS50", 1 + 12)) {
+
+ ByteBuf buf = Unpooled.wrappedBuffer(DataConverter.parseHex(payload));
+
+ buf.readUnsignedByte();
+ buf.readUnsignedByte();
+ buf.readUnsignedByte(); // header
+
+ int batteryCount = buf.readUnsignedByte();
+ for (int i = 1; i <= 24; i++) {
+ int voltage = buf.readUnsignedShortLE();
+ if (i <= batteryCount) {
+ position.set("battery" + i, voltage * 0.001);
+ }
+ }
+
+ position.set(Position.KEY_CHARGE, buf.readUnsignedByte() == 0);
+ position.set("current", buf.readUnsignedShortLE() * 0.1);
+ position.set(Position.KEY_BATTERY, buf.readUnsignedShortLE() * 0.01);
+ position.set(Position.KEY_BATTERY_LEVEL, buf.readUnsignedByte());
+ position.set("batteryOverheat", buf.readUnsignedByte() > 0);
+ position.set("chargeProtection", buf.readUnsignedByte() > 0);
+ position.set("dischargeProtection", buf.readUnsignedByte() > 0);
+ buf.readUnsignedByte(); // drop line
+ buf.readUnsignedByte(); // balanced
+ position.set("cycles", buf.readUnsignedShortLE());
+ position.set("faultAlarm", buf.readUnsignedByte());
+
+ buf.skipBytes(6);
+
+ int temperatureCount = buf.readUnsignedByte();
+ position.set("powerTemp", buf.readUnsignedByte() - 40);
+ position.set("equilibriumTemp", buf.readUnsignedByte() - 40);
+ for (int i = 1; i <= 7; i++) {
+ int temperature = buf.readUnsignedByte() - 40;
+ if (i <= temperatureCount) {
+ position.set("batteryTemp" + i, temperature);
+ }
+ }
+
+ position.set("calibrationCapacity", buf.readUnsignedShortLE() * 0.01);
+ position.set("dischargeCapacity", buf.readUnsignedIntLE());
+
+ } else {
+
+ String[] values = payload.split(",");
+ for (String value : values) {
+ String[] pair = value.split(":");
+ int key = Integer.parseInt(pair[0], 16);
+ ByteBuf buf = Unpooled.wrappedBuffer(DataConverter.parseHex(pair[1]));
+ switch (key) {
+ case 0x90:
+ position.set("cumulativeVoltage", buf.readUnsignedShortLE() * 0.1);
+ position.set("gatherVoltage", buf.readUnsignedShortLE() * 0.1);
+ position.set("current", (buf.readUnsignedShortLE() - 30000) * 0.1);
+ position.set("soc", buf.readUnsignedShortLE() * 0.1);
+ break;
+ case 0x91:
+ position.set("maxCellVoltage", buf.readUnsignedShortLE() * 0.001);
+ position.set("maxCellVoltageCount", buf.readUnsignedByte());
+ position.set("minCellVoltage", buf.readUnsignedShortLE() * 0.001);
+ position.set("minCellVoltageCount", buf.readUnsignedByte());
+ break;
+ case 0x92:
+ position.set("maxTemp", buf.readUnsignedByte() - 40);
+ position.set("maxTempCount", buf.readUnsignedByte());
+ position.set("minTemp", buf.readUnsignedByte() - 40);
+ position.set("minTempCount", buf.readUnsignedByte());
+ break;
+ case 0x96:
+ buf.readUnsignedByte(); // frame
+ while (buf.isReadable()) {
+ position.set("cellTemp" + buf.readerIndex(), buf.readUnsignedByte() - 40);
+ }
+ break;
+ default:
+ break;
+ }
+
+ }
+
+ }
+
+ return position;
+ }
+
@Override
protected Object decode(
Channel channel, SocketAddress remoteAddress, Object msg) throws Exception {
@@ -477,6 +580,8 @@ public class Tk103ProtocolDecoder extends BaseProtocolDecoder {
return decodeLbsWifi(channel, remoteAddress, sentence);
} else if (sentence.contains("BV00")) {
return decodeVin(channel, remoteAddress, sentence);
+ } else if (sentence.contains("BS50") || sentence.contains("BS51")) {
+ return decodeBms(channel, remoteAddress, sentence);
}
Parser parser = new Parser(PATTERN, sentence);
diff --git a/src/main/java/org/traccar/protocol/Tlt2hProtocol.java b/src/main/java/org/traccar/protocol/Tlt2hProtocol.java
index b10271f7d..6763e9b6b 100644
--- a/src/main/java/org/traccar/protocol/Tlt2hProtocol.java
+++ b/src/main/java/org/traccar/protocol/Tlt2hProtocol.java
@@ -23,7 +23,7 @@ import org.traccar.PipelineBuilder;
import org.traccar.TrackerServer;
import org.traccar.config.Config;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class Tlt2hProtocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/Tlt2hProtocolDecoder.java b/src/main/java/org/traccar/protocol/Tlt2hProtocolDecoder.java
index e85bdf9b3..6be3d2dc3 100644
--- a/src/main/java/org/traccar/protocol/Tlt2hProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/Tlt2hProtocolDecoder.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2013 - 2022 Anton Tananaev (anton@traccar.org)
+ * Copyright 2013 - 2024 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.
@@ -55,16 +55,20 @@ public class Tlt2hProtocolDecoder extends BaseProtocolDecoder {
private static final Pattern PATTERN_POSITION = new PatternBuilder()
.text("#")
- .number("(?:(dd)|x*)") // cell or voltage
+ .number("(?:(dd|dddd)|x*)") // cell or voltage
.groupBegin()
- .number("#(d+),") // mcc
+ .text("#")
+ .groupBegin()
+ .number("(d+),") // mcc
.number("(d+),") // mnc
.number("(x+),") // lac
.number("(x+)") // cell id
.groupEnd("?")
+ .groupEnd("?")
.text("$GPRMC,")
- .number("(dd)(dd)(dd).d+,") // time (hhmmss.sss)
+ .number("(?:(dd)(dd)(dd).d+)?,") // time (hhmmss.sss)
.expression("([AVL]),") // validity
+ .groupBegin()
.number("(d+)(dd.d+),") // latitude
.expression("([NS]),")
.number("(d+)(dd.d+),") // longitude
@@ -72,14 +76,16 @@ public class Tlt2hProtocolDecoder extends BaseProtocolDecoder {
.number("(d+.?d*)?,") // speed
.number("(d+.?d*)?,") // course
.number("(dd)(dd)(dd)") // date (ddmmyy)
+ .groupEnd("?")
.any()
.compile();
private static final Pattern PATTERN_WIFI = new PatternBuilder()
.text("#")
- .number("(?:(dd)|x+)") // cell or voltage
+ .number("(?:(dd|dddd)|x+)") // cell or voltage
+ .expression("#?")
.groupBegin()
- .number("#(d+),") // mcc
+ .number("(d+),") // mcc
.number("(d+),") // mnc
.number("(x+),") // lac
.number("(x+)") // cell id
@@ -178,7 +184,8 @@ public class Tlt2hProtocolDecoder extends BaseProtocolDecoder {
if (parser.matches()) {
if (parser.hasNext()) {
- position.set(Position.KEY_BATTERY, parser.nextInt() * 0.1);
+ int voltage = parser.nextInt();
+ position.set(Position.KEY_BATTERY, voltage > 100 ? voltage * 0.001 : voltage * 0.1);
}
if (parser.hasNext(4)) {
@@ -188,17 +195,26 @@ public class Tlt2hProtocolDecoder extends BaseProtocolDecoder {
position.setNetwork(network);
}
- DateBuilder dateBuilder = new DateBuilder()
- .setTime(parser.nextInt(), parser.nextInt(), parser.nextInt());
+ DateBuilder dateBuilder = new DateBuilder();
+ if (parser.hasNext(3)) {
+ dateBuilder.setTime(parser.nextInt(), parser.nextInt(), parser.nextInt());
+ }
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(), parser.nextInt(), parser.nextInt());
- position.setTime(dateBuilder.getDate());
+ if (parser.hasNext()) {
+
+ position.setLatitude(parser.nextCoordinate());
+ position.setLongitude(parser.nextCoordinate());
+ position.setSpeed(parser.nextDouble(0));
+ position.setCourse(parser.nextDouble(0));
+
+ dateBuilder.setDateReverse(parser.nextInt(), parser.nextInt(), parser.nextInt());
+ position.setTime(dateBuilder.getDate());
+
+ } else {
+ getLastLocation(position, null);
+ }
} else {
continue;
@@ -209,7 +225,10 @@ public class Tlt2hProtocolDecoder extends BaseProtocolDecoder {
parser = new Parser(PATTERN_WIFI, message);
if (parser.matches()) {
- position.set(Position.KEY_BATTERY, parser.nextInt() * 0.1);
+ if (parser.hasNext()) {
+ int voltage = parser.nextInt();
+ position.set(Position.KEY_BATTERY, voltage > 100 ? voltage * 0.001 : voltage * 0.1);
+ }
Network network = new Network();
if (parser.hasNext(4)) {
@@ -230,6 +249,8 @@ public class Tlt2hProtocolDecoder extends BaseProtocolDecoder {
dateBuilder.setDateReverse(parser.nextInt(), parser.nextInt(), parser.nextInt());
getLastLocation(position, dateBuilder.getDate());
+ } else {
+ continue;
}
} else {
diff --git a/src/main/java/org/traccar/protocol/TlvProtocol.java b/src/main/java/org/traccar/protocol/TlvProtocol.java
index 9d83388c9..f99676d23 100644
--- a/src/main/java/org/traccar/protocol/TlvProtocol.java
+++ b/src/main/java/org/traccar/protocol/TlvProtocol.java
@@ -21,7 +21,7 @@ import org.traccar.PipelineBuilder;
import org.traccar.TrackerServer;
import org.traccar.config.Config;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class TlvProtocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/TmgProtocol.java b/src/main/java/org/traccar/protocol/TmgProtocol.java
index e078c425b..dbba648be 100644
--- a/src/main/java/org/traccar/protocol/TmgProtocol.java
+++ b/src/main/java/org/traccar/protocol/TmgProtocol.java
@@ -22,7 +22,7 @@ import org.traccar.PipelineBuilder;
import org.traccar.TrackerServer;
import org.traccar.config.Config;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class TmgProtocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/TopflytechProtocol.java b/src/main/java/org/traccar/protocol/TopflytechProtocol.java
index 339d2fc8d..a658235ab 100644
--- a/src/main/java/org/traccar/protocol/TopflytechProtocol.java
+++ b/src/main/java/org/traccar/protocol/TopflytechProtocol.java
@@ -23,7 +23,7 @@ import org.traccar.PipelineBuilder;
import org.traccar.TrackerServer;
import org.traccar.config.Config;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class TopflytechProtocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/TopinProtocol.java b/src/main/java/org/traccar/protocol/TopinProtocol.java
index b15373d71..1a558f617 100644
--- a/src/main/java/org/traccar/protocol/TopinProtocol.java
+++ b/src/main/java/org/traccar/protocol/TopinProtocol.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2019 - 2021 Anton Tananaev (anton@traccar.org)
+ * Copyright 2019 - 2023 Anton Tananaev (anton@traccar.org)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -19,16 +19,19 @@ import org.traccar.BaseProtocol;
import org.traccar.PipelineBuilder;
import org.traccar.TrackerServer;
import org.traccar.config.Config;
+import org.traccar.config.Keys;
import org.traccar.model.Command;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class TopinProtocol extends BaseProtocol {
@Inject
public TopinProtocol(Config config) {
- setSupportedDataCommands(
- Command.TYPE_SOS_NUMBER);
+ if (!config.getBoolean(Keys.PROTOCOL_DISABLE_COMMANDS.withPrefix(getName()))) {
+ setSupportedDataCommands(
+ Command.TYPE_SOS_NUMBER);
+ }
addServer(new TrackerServer(config, getName(), false) {
@Override
protected void addProtocolHandlers(PipelineBuilder pipeline, Config config) {
diff --git a/src/main/java/org/traccar/protocol/TopinProtocolDecoder.java b/src/main/java/org/traccar/protocol/TopinProtocolDecoder.java
index a1d5481db..c7b816818 100644
--- a/src/main/java/org/traccar/protocol/TopinProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/TopinProtocolDecoder.java
@@ -48,7 +48,12 @@ public class TopinProtocolDecoder extends BaseProtocolDecoder {
public static final int MSG_GPS = 0x10;
public static final int MSG_GPS_OFFLINE = 0x11;
public static final int MSG_STATUS = 0x13;
+ public static final int MSG_SLEEP = 0x14;
+ public static final int MSG_FACTORY_RESET = 0x15;
public static final int MSG_WIFI_OFFLINE = 0x17;
+ public static final int MSG_LBS_WIFI = 0x18;
+ public static final int MSG_LBS_WIFI_OFFLINE = 0x19;
+ public static final int MSG_LBS_WIFI_2 = 0x1A;
public static final int MSG_TIME_UPDATE = 0x30;
public static final int MSG_SOS_NUMBER = 0x41;
public static final int MSG_WIFI = 0x69;
@@ -216,7 +221,8 @@ public class TopinProtocolDecoder extends BaseProtocolDecoder {
return position;
- } else if (type == MSG_WIFI || type == MSG_WIFI_OFFLINE) {
+ } else if (type == MSG_WIFI || type == MSG_WIFI_OFFLINE
+ || type == MSG_LBS_WIFI || type == MSG_LBS_WIFI_2 || type == MSG_LBS_WIFI_OFFLINE) {
Position position = new Position(getProtocolName());
position.setDeviceId(deviceSession.getDeviceId());
diff --git a/src/main/java/org/traccar/protocol/TotemProtocol.java b/src/main/java/org/traccar/protocol/TotemProtocol.java
index 9ab36fd0b..b02d4f1fc 100644
--- a/src/main/java/org/traccar/protocol/TotemProtocol.java
+++ b/src/main/java/org/traccar/protocol/TotemProtocol.java
@@ -23,7 +23,7 @@ import org.traccar.TrackerServer;
import org.traccar.config.Config;
import org.traccar.model.Command;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class TotemProtocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/TotemProtocolDecoder.java b/src/main/java/org/traccar/protocol/TotemProtocolDecoder.java
index 9d0d794f8..6f039c324 100644
--- a/src/main/java/org/traccar/protocol/TotemProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/TotemProtocolDecoder.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2013 - 2020 Anton Tananaev (anton@traccar.org)
+ * Copyright 2013 - 2023 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.
@@ -135,7 +135,7 @@ public class TotemProtocolDecoder extends BaseProtocolDecoder {
private static final Pattern PATTERN4 = new PatternBuilder()
.text("$$") // header
.number("dddd") // length
- .number("(xx)") // type
+ .number("xx") // type
.number("(d+)|") // imei
.number("(x{8})") // status
.number("(dd)(dd)(dd)") // date (yymmdd)
@@ -176,7 +176,21 @@ public class TotemProtocolDecoder extends BaseProtocolDecoder {
.any()
.compile();
- private static final Pattern PATTERN_OBD = new PatternBuilder()
+ private static final Pattern PATTERN_E2 = new PatternBuilder()
+ .text("$$") // header
+ .number("dddd") // length
+ .number("xx") // type
+ .number("(d+)|") // imei
+ .number("(dd)(dd)(dd)") // date (yymmdd)
+ .number("(dd)(dd)(dd),") // time (hhmmss)
+ .number("(-?d+.d+),") // longitude
+ .number("(-?d+.d+),") // latitude
+ .expression("(.+)") // rfid
+ .number("|xx") // checksum
+ .any()
+ .compile();
+
+ private static final Pattern PATTERN_E5 = new PatternBuilder()
.text("$$") // header
.number("dddd") // length
.number("xx") // type
@@ -257,7 +271,20 @@ public class TotemProtocolDecoder extends BaseProtocolDecoder {
}
}
- private boolean decode12(Position position, Parser parser, Pattern pattern) {
+ private Position decode12(Channel channel, SocketAddress remoteAddress, String sentence, Pattern pattern) {
+
+ Parser parser = new Parser(pattern, sentence);
+ 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());
if (parser.hasNext()) {
position.set(Position.KEY_ALARM, decodeAlarm123(Short.parseShort(parser.next(), 16)));
@@ -283,7 +310,7 @@ public class TotemProtocolDecoder extends BaseProtocolDecoder {
year = parser.nextInt(0);
}
if (year == 0) {
- return false; // ignore invalid data
+ return null; // ignore invalid data
}
dateBuilder.setDate(year, month, day);
position.setTime(dateBuilder.getDate());
@@ -331,10 +358,23 @@ public class TotemProtocolDecoder extends BaseProtocolDecoder {
position.set(Position.PREFIX_TEMP + 1, parser.next());
position.set(Position.KEY_ODOMETER, parser.nextDouble(0) * 1000);
- return true;
+ return position;
}
- private boolean decode3(Position position, Parser parser) {
+ private Position decode3(Channel channel, SocketAddress remoteAddress, String sentence) {
+
+ Parser parser = new Parser(PATTERN3, sentence);
+ 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());
if (parser.hasNext()) {
position.set(Position.KEY_ALARM, decodeAlarm123(Short.parseShort(parser.next(), 16)));
@@ -363,10 +403,36 @@ public class TotemProtocolDecoder extends BaseProtocolDecoder {
position.setLatitude(parser.nextCoordinate());
position.setLongitude(parser.nextCoordinate());
- return true;
+ return position;
}
- private boolean decode4(Position position, Parser parser) {
+ private Position decode4(Channel channel, SocketAddress remoteAddress, String sentence) {
+
+ int type = Integer.parseInt(sentence.substring(6, 8), 16);
+
+ switch (type) {
+ case 0xE2:
+ return decodeE2(channel, remoteAddress, sentence);
+ case 0xE5:
+ return decodeE5(channel, remoteAddress, sentence);
+ default:
+ break;
+ }
+
+ Parser parser = new Parser(PATTERN4, sentence);
+ 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.set(Position.KEY_ALARM, decodeAlarm4(type));
long status = parser.nextHexLong();
@@ -427,10 +493,48 @@ public class TotemProtocolDecoder extends BaseProtocolDecoder {
position.setLatitude(parser.nextCoordinate());
position.setLongitude(parser.nextCoordinate());
- return true;
+ return position;
}
- private boolean decodeObd(Position position, Parser parser) {
+ private Position decodeE2(Channel channel, SocketAddress remoteAddress, String sentence) {
+
+ Parser parser = new Parser(PATTERN_E2, sentence);
+ 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.setValid(true);
+ position.setTime(parser.nextDateTime());
+ position.setLongitude(parser.nextDouble());
+ position.setLatitude(parser.nextDouble());
+
+ position.set(Position.KEY_DRIVER_UNIQUE_ID, parser.next());
+
+ return position;
+ }
+
+ private Position decodeE5(Channel channel, SocketAddress remoteAddress, String sentence) {
+
+ Parser parser = new Parser(PATTERN_E5, sentence);
+ 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.setValid(true);
position.setTime(parser.nextDateTime());
@@ -451,7 +555,7 @@ public class TotemProtocolDecoder extends BaseProtocolDecoder {
position.set(Position.KEY_THROTTLE, parser.nextInt());
position.set(Position.KEY_FUEL_LEVEL, parser.nextInt());
- return true;
+ return position;
}
@Override
@@ -459,50 +563,23 @@ public class TotemProtocolDecoder extends BaseProtocolDecoder {
Channel channel, SocketAddress remoteAddress, Object msg) throws Exception {
String sentence = (String) msg;
- Pattern pattern = PATTERN3;
- if (sentence.contains("$Cloud")) {
- pattern = PATTERN_OBD;
- } else if (sentence.charAt(2) == '0') {
- pattern = PATTERN4;
+
+ Position position;
+ if (sentence.charAt(2) == '0') {
+ position = decode4(channel, remoteAddress, sentence);
} else if (sentence.contains("$GPRMC")) {
- pattern = PATTERN1;
+ position = decode12(channel, remoteAddress, sentence, PATTERN1);
} else {
int index = sentence.indexOf('|');
if (index != -1 && sentence.indexOf('|', index + 1) != -1) {
- pattern = PATTERN2;
+ position = decode12(channel, remoteAddress, sentence, PATTERN2);
+ } else {
+ position = decode3(channel, remoteAddress, sentence);
}
}
- Parser parser = new Parser(pattern, sentence);
- if (!parser.matches()) {
- return null;
- }
-
- Position position = new Position(getProtocolName());
-
- if (pattern == PATTERN4) {
- position.set(Position.KEY_ALARM, decodeAlarm4(parser.nextHexInt()));
- }
-
- DeviceSession deviceSession = getDeviceSession(channel, remoteAddress, parser.next());
- if (deviceSession == null) {
- return null;
- }
- position.setDeviceId(deviceSession.getDeviceId());
-
- boolean result;
- if (pattern == PATTERN1 || pattern == PATTERN2) {
- result = decode12(position, parser, pattern);
- } else if (pattern == PATTERN3) {
- result = decode3(position, parser);
- } else if (pattern == PATTERN4) {
- result = decode4(position, parser);
- } else {
- result = decodeObd(position, parser);
- }
-
if (channel != null) {
- if (pattern == PATTERN4) {
+ if (sentence.charAt(2) == '0') {
String response = "$$0014AA" + sentence.substring(sentence.length() - 6, sentence.length() - 2);
response += String.format("%02X", Checksum.xor(response)).toUpperCase();
channel.writeAndFlush(new NetworkMessage(response, remoteAddress));
@@ -511,7 +588,7 @@ public class TotemProtocolDecoder extends BaseProtocolDecoder {
}
}
- return result ? position : null;
+ return position;
}
}
diff --git a/src/main/java/org/traccar/protocol/Tr20Protocol.java b/src/main/java/org/traccar/protocol/Tr20Protocol.java
index 615fdab28..3b3fc02b6 100644
--- a/src/main/java/org/traccar/protocol/Tr20Protocol.java
+++ b/src/main/java/org/traccar/protocol/Tr20Protocol.java
@@ -23,7 +23,7 @@ import org.traccar.PipelineBuilder;
import org.traccar.TrackerServer;
import org.traccar.config.Config;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class Tr20Protocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/Tr900Protocol.java b/src/main/java/org/traccar/protocol/Tr900Protocol.java
index 162cbe651..c5f357604 100644
--- a/src/main/java/org/traccar/protocol/Tr900Protocol.java
+++ b/src/main/java/org/traccar/protocol/Tr900Protocol.java
@@ -23,7 +23,7 @@ import org.traccar.PipelineBuilder;
import org.traccar.TrackerServer;
import org.traccar.config.Config;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class Tr900Protocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/TrackboxProtocol.java b/src/main/java/org/traccar/protocol/TrackboxProtocol.java
index 4236144a3..eadcd07f9 100644
--- a/src/main/java/org/traccar/protocol/TrackboxProtocol.java
+++ b/src/main/java/org/traccar/protocol/TrackboxProtocol.java
@@ -23,7 +23,7 @@ import org.traccar.PipelineBuilder;
import org.traccar.TrackerServer;
import org.traccar.config.Config;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class TrackboxProtocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/TrakMateProtocol.java b/src/main/java/org/traccar/protocol/TrakMateProtocol.java
index b7637e6f3..f4e7c5e60 100644
--- a/src/main/java/org/traccar/protocol/TrakMateProtocol.java
+++ b/src/main/java/org/traccar/protocol/TrakMateProtocol.java
@@ -23,7 +23,7 @@ import org.traccar.PipelineBuilder;
import org.traccar.TrackerServer;
import org.traccar.config.Config;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class TrakMateProtocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/TramigoFrameDecoder.java b/src/main/java/org/traccar/protocol/TramigoFrameDecoder.java
index e4c94dc77..72cadf21a 100644
--- a/src/main/java/org/traccar/protocol/TramigoFrameDecoder.java
+++ b/src/main/java/org/traccar/protocol/TramigoFrameDecoder.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2015 - 2019 Anton Tananaev (anton@traccar.org)
+ * Copyright 2015 - 2023 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.
@@ -29,9 +29,13 @@ public class TramigoFrameDecoder extends BaseFrameDecoder {
return null;
}
+ int protocol = buf.getUnsignedByte(buf.readerIndex());
+
int length;
- if (buf.getUnsignedByte(buf.readerIndex()) == 0x80) {
+ if (protocol == 0x80) {
length = buf.getUnsignedShortLE(buf.readerIndex() + 6);
+ } else if (protocol == 0x02 || protocol == 0x04) {
+ length = buf.getUnsignedShortLE(buf.readerIndex() + 1);
} else {
length = buf.getUnsignedShort(buf.readerIndex() + 6);
}
diff --git a/src/main/java/org/traccar/protocol/TramigoProtocol.java b/src/main/java/org/traccar/protocol/TramigoProtocol.java
index 79a59abd3..5d8baf2a9 100644
--- a/src/main/java/org/traccar/protocol/TramigoProtocol.java
+++ b/src/main/java/org/traccar/protocol/TramigoProtocol.java
@@ -20,7 +20,7 @@ import org.traccar.PipelineBuilder;
import org.traccar.TrackerServer;
import org.traccar.config.Config;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class TramigoProtocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/TramigoProtocolDecoder.java b/src/main/java/org/traccar/protocol/TramigoProtocolDecoder.java
index 21dd78da3..4a9a9a58f 100644
--- a/src/main/java/org/traccar/protocol/TramigoProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/TramigoProtocolDecoder.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2014 - 2018 Anton Tananaev (anton@traccar.org)
+ * Copyright 2014 - 2023 Anton Tananaev (anton@traccar.org)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -19,6 +19,8 @@ import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.Channel;
import org.traccar.BaseProtocolDecoder;
+import org.traccar.helper.BitUtil;
+import org.traccar.helper.Checksum;
import org.traccar.session.DeviceSession;
import org.traccar.NetworkMessage;
import org.traccar.Protocol;
@@ -29,6 +31,7 @@ import org.traccar.model.Position;
import java.net.SocketAddress;
import java.nio.charset.StandardCharsets;
import java.text.DateFormat;
+import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
@@ -42,9 +45,6 @@ public class TramigoProtocolDecoder extends BaseProtocolDecoder {
super(protocol);
}
- public static final int MSG_COMPACT = 0x0100;
- public static final int MSG_FULL = 0x00FE;
-
private static final String[] DIRECTIONS = new String[] {"N", "NE", "E", "SE", "S", "SW", "W", "NW"};
@Override
@@ -54,34 +54,47 @@ public class TramigoProtocolDecoder extends BaseProtocolDecoder {
ByteBuf buf = (ByteBuf) msg;
int protocol = buf.readUnsignedByte();
- boolean legacy = protocol == 0x80;
+
+ if (protocol == 0x01) {
+ return decode01(channel, remoteAddress, buf);
+ } else if (protocol == 0x04) {
+ return decode04(channel, remoteAddress, buf);
+ } else if (protocol == 0x80) {
+ return decode80(channel, remoteAddress, buf);
+ }
+
+ return null;
+ }
+
+ private Position decode01(Channel channel, SocketAddress remoteAddress, ByteBuf buf) {
buf.readUnsignedByte(); // version id
- int index = legacy ? buf.readUnsignedShort() : buf.readUnsignedShortLE();
- int type = legacy ? buf.readUnsignedShort() : buf.readUnsignedShortLE();
- buf.readUnsignedShort(); // length
- buf.readUnsignedShort(); // mask
- buf.readUnsignedShort(); // checksum
- long id = legacy ? buf.readUnsignedInt() : buf.readUnsignedIntLE();
- buf.readUnsignedInt(); // time
+ int index = buf.readUnsignedShortLE();
+ int type = buf.readUnsignedShortLE();
- Position position = new Position(getProtocolName());
- position.set(Position.KEY_INDEX, index);
- position.setValid(true);
+ if (type == 0x0100 || type == 0x00FE) {
- DeviceSession deviceSession = getDeviceSession(channel, remoteAddress, String.valueOf(id));
- if (deviceSession == null) {
- return null;
- }
- position.setDeviceId(deviceSession.getDeviceId());
+ buf.readUnsignedShort(); // length
+ buf.readUnsignedShort(); // mask
+ buf.readUnsignedShort(); // checksum
+ long id = buf.readUnsignedIntLE();
+ buf.readUnsignedInt(); // time
- if (protocol == 0x01 && (type == MSG_COMPACT || type == MSG_FULL)) {
+ DeviceSession deviceSession = getDeviceSession(channel, remoteAddress, String.valueOf(id));
+ if (deviceSession == null) {
+ return null;
+ }
+
+ Position position = new Position(getProtocolName());
+ position.setDeviceId(deviceSession.getDeviceId());
+ position.set(Position.KEY_INDEX, index);
// need to send ack?
buf.readUnsignedShortLE(); // report trigger
buf.readUnsignedShortLE(); // state flag
+ position.setValid(true);
position.setLatitude(buf.readUnsignedIntLE() * 0.0000001);
position.setLongitude(buf.readUnsignedIntLE() * 0.0000001);
@@ -105,56 +118,183 @@ public class TramigoProtocolDecoder extends BaseProtocolDecoder {
return position;
- } else if (legacy) {
+ }
- if (channel != null) {
- channel.writeAndFlush(new NetworkMessage(
- Unpooled.copiedBuffer("gprs,ack," + index, StandardCharsets.US_ASCII), remoteAddress));
- }
+ return null;
- String sentence = buf.toString(StandardCharsets.US_ASCII);
+ }
- Pattern pattern = Pattern.compile("(-?\\d+\\.\\d+), (-?\\d+\\.\\d+)");
- Matcher matcher = pattern.matcher(sentence);
- if (!matcher.find()) {
- return null;
- }
- position.setLatitude(Double.parseDouble(matcher.group(1)));
- position.setLongitude(Double.parseDouble(matcher.group(2)));
-
- pattern = Pattern.compile("([NSWE]{1,2}) with speed (\\d+) km/h");
- matcher = pattern.matcher(sentence);
- if (matcher.find()) {
- for (int i = 0; i < DIRECTIONS.length; i++) {
- if (matcher.group(1).equals(DIRECTIONS[i])) {
- position.setCourse(i * 45.0);
- break;
- }
- }
- position.setSpeed(UnitsConverter.knotsFromKph(Double.parseDouble(matcher.group(2))));
- }
+ private Position decode04(Channel channel, SocketAddress remoteAddress, ByteBuf buf) {
- pattern = Pattern.compile("(\\d{1,2}:\\d{2}(:\\d{2})? \\w{3} \\d{1,2})");
- matcher = pattern.matcher(sentence);
- if (!matcher.find()) {
- return null;
- }
- DateFormat dateFormat = new SimpleDateFormat(
- matcher.group(2) != null ? "HH:mm:ss MMM d yyyy" : "HH:mm MMM d yyyy", Locale.ENGLISH);
- position.setTime(DateUtil.correctYear(
- dateFormat.parse(matcher.group(1) + " " + Calendar.getInstance().get(Calendar.YEAR))));
-
- if (sentence.contains("Ignition on detected")) {
- position.set(Position.KEY_IGNITION, true);
- } else if (sentence.contains("Ignition off detected")) {
- position.set(Position.KEY_IGNITION, false);
+ buf.readUnsignedShortLE(); // length
+ buf.readUnsignedShortLE(); // checksum
+ int index = buf.readUnsignedShortLE();
+ long id1 = buf.readUnsignedIntLE();
+ long id2 = buf.readUnsignedIntLE();
+ long time = buf.readUnsignedIntLE();
+
+ String id = String.format("%08d%07d", id1, id2);
+ DeviceSession deviceSession = getDeviceSession(channel, remoteAddress, id);
+ if (deviceSession == null) {
+ return null;
+ }
+
+ if (channel != null) {
+ ByteBuf response = Unpooled.buffer();
+ response.writeByte(0x04); // protocol
+ response.writeShortLE(24); // length
+ response.writeShortLE(0); // checksum
+ response.writeShortLE(index);
+ response.writeIntLE((int) id1);
+ response.writeIntLE((int) id2);
+ response.writeIntLE((int) time);
+
+ response.writeByte(0xff); // acknowledgement
+ response.writeShortLE(index);
+ response.writeShortLE(0); // success
+
+ response.setShortLE(3, Checksum.crc16(Checksum.CRC16_CCITT_FALSE, response.nioBuffer()));
+
+ channel.writeAndFlush(new NetworkMessage(response, channel.remoteAddress()));
+ }
+
+ Position position = new Position(getProtocolName());
+ position.setDeviceId(deviceSession.getDeviceId());
+ position.set(Position.KEY_INDEX, index);
+
+ position.setDeviceTime(new Date(time * 1000));
+
+ while (buf.isReadable()) {
+ int type = buf.readUnsignedByte();
+ switch (type) {
+ case 0:
+ position.set(Position.KEY_EVENT, buf.readUnsignedShortLE());
+ buf.readUnsignedIntLE(); // event data
+
+ int status = buf.readUnsignedShortLE();
+ position.set(Position.KEY_IGNITION, BitUtil.check(status, 5));
+ position.set(Position.KEY_STATUS, status);
+
+ position.setValid(true);
+ position.setLatitude(buf.readIntLE() * 0.00001);
+ position.setLongitude(buf.readIntLE() * 0.00001);
+ position.setSpeed(UnitsConverter.knotsFromKph(buf.readUnsignedShortLE()));
+ position.setCourse(buf.readUnsignedShortLE());
+
+ position.set(Position.KEY_RSSI, buf.readUnsignedByte());
+ position.set(Position.KEY_GPS, buf.readUnsignedByte());
+ position.set(Position.KEY_BATTERY_LEVEL, buf.readUnsignedByte());
+ position.set(Position.KEY_ODOMETER_TRIP, buf.readUnsignedShortLE());
+ position.set("maxAcceleration", buf.readUnsignedShortLE() * 0.001);
+ position.set("maxDeceleration", buf.readUnsignedShortLE() * 0.001);
+ buf.readUnsignedShortLE(); // bearing to landmark
+ buf.readUnsignedIntLE(); // distance to landmark
+
+ position.setFixTime(new Date(buf.readUnsignedIntLE() * 1000));
+
+ buf.readUnsignedByte(); // reserved
+ break;
+ case 1:
+ buf.skipBytes(buf.readUnsignedShortLE() - 3); // landmark
+ break;
+ case 4:
+ buf.skipBytes(53); // trip
+ break;
+ case 20:
+ buf.skipBytes(32); // extended
+ break;
+ case 22:
+ buf.readUnsignedByte(); // zone flag
+ buf.skipBytes(buf.readUnsignedShortLE()); // zone name
+ break;
+ case 30:
+ buf.skipBytes(79); // system status
+ break;
+ case 40:
+ buf.skipBytes(40); // analog
+ break;
+ case 50:
+ buf.skipBytes(buf.readUnsignedShortLE() - 3); // console
+ break;
+ case 255:
+ buf.skipBytes(4); // acknowledgement
+ break;
+ default:
+ throw new IllegalArgumentException(String.format("Unknown type %d", type));
}
+ }
- return position;
+ return position.getValid() ? position : null;
+
+ }
+ private Position decode80(Channel channel, SocketAddress remoteAddress, ByteBuf buf) throws ParseException {
+
+ buf.readUnsignedByte(); // version id
+ int index = buf.readUnsignedShort();
+ buf.readUnsignedShort(); // type
+
+ buf.readUnsignedShort(); // length
+ buf.readUnsignedShort(); // mask
+ buf.readUnsignedShort(); // checksum
+ long id = buf.readUnsignedInt();
+ buf.readUnsignedInt(); // time
+
+ DeviceSession deviceSession = getDeviceSession(channel, remoteAddress, String.valueOf(id));
+ if (deviceSession == null) {
+ return null;
}
- return null;
+ Position position = new Position(getProtocolName());
+ position.setDeviceId(deviceSession.getDeviceId());
+ position.set(Position.KEY_INDEX, index);
+
+ if (channel != null) {
+ channel.writeAndFlush(new NetworkMessage(
+ Unpooled.copiedBuffer("gprs,ack," + index, StandardCharsets.US_ASCII), remoteAddress));
+ }
+
+ String sentence = buf.toString(StandardCharsets.US_ASCII);
+
+ Pattern pattern = Pattern.compile("(-?\\d+\\.\\d+), (-?\\d+\\.\\d+)");
+ Matcher matcher = pattern.matcher(sentence);
+ if (!matcher.find()) {
+ return null;
+ }
+ position.setLatitude(Double.parseDouble(matcher.group(1)));
+ position.setLongitude(Double.parseDouble(matcher.group(2)));
+ position.setValid(true);
+
+ pattern = Pattern.compile("([NSWE]{1,2}) with speed (\\d+) km/h");
+ matcher = pattern.matcher(sentence);
+ if (matcher.find()) {
+ for (int i = 0; i < DIRECTIONS.length; i++) {
+ if (matcher.group(1).equals(DIRECTIONS[i])) {
+ position.setCourse(i * 45.0);
+ break;
+ }
+ }
+ position.setSpeed(UnitsConverter.knotsFromKph(Double.parseDouble(matcher.group(2))));
+ }
+
+ pattern = Pattern.compile("(\\d{1,2}:\\d{2}(:\\d{2})? \\w{3} \\d{1,2})");
+ matcher = pattern.matcher(sentence);
+ if (!matcher.find()) {
+ return null;
+ }
+ DateFormat dateFormat = new SimpleDateFormat(
+ matcher.group(2) != null ? "HH:mm:ss MMM d yyyy" : "HH:mm MMM d yyyy", Locale.ENGLISH);
+ position.setTime(DateUtil.correctYear(
+ dateFormat.parse(matcher.group(1) + " " + Calendar.getInstance().get(Calendar.YEAR))));
+
+ if (sentence.contains("Ignition on detected")) {
+ position.set(Position.KEY_IGNITION, true);
+ } else if (sentence.contains("Ignition off detected")) {
+ position.set(Position.KEY_IGNITION, false);
+ }
+
+ return position;
+
}
}
diff --git a/src/main/java/org/traccar/protocol/TranSyncProtocol.java b/src/main/java/org/traccar/protocol/TranSyncProtocol.java
new file mode 100644
index 000000000..fb37a1ab4
--- /dev/null
+++ b/src/main/java/org/traccar/protocol/TranSyncProtocol.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2023 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.LengthFieldBasedFrameDecoder;
+import org.traccar.BaseProtocol;
+import org.traccar.PipelineBuilder;
+import org.traccar.TrackerServer;
+import org.traccar.config.Config;
+
+import jakarta.inject.Inject;
+
+public class TranSyncProtocol extends BaseProtocol {
+
+ @Inject
+ public TranSyncProtocol(Config config) {
+ addServer(new TrackerServer(config, getName(), false) {
+ @Override
+ protected void addProtocolHandlers(PipelineBuilder pipeline, Config config) {
+ pipeline.addLast(new LengthFieldBasedFrameDecoder(256, 2, 1, 2, 0));
+ pipeline.addLast(new TranSyncProtocolDecoder(TranSyncProtocol.this));
+ }
+ });
+ }
+
+}
diff --git a/src/main/java/org/traccar/protocol/TranSyncProtocolDecoder.java b/src/main/java/org/traccar/protocol/TranSyncProtocolDecoder.java
new file mode 100644
index 000000000..816b5d2cf
--- /dev/null
+++ b/src/main/java/org/traccar/protocol/TranSyncProtocolDecoder.java
@@ -0,0 +1,166 @@
+/*
+ * Copyright 2023 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.buffer.ByteBufUtil;
+import io.netty.channel.Channel;
+import org.traccar.BaseProtocolDecoder;
+import org.traccar.Protocol;
+import org.traccar.helper.BitUtil;
+import org.traccar.helper.DateBuilder;
+import org.traccar.helper.UnitsConverter;
+import org.traccar.model.CellTower;
+import org.traccar.model.Network;
+import org.traccar.model.Position;
+import org.traccar.session.DeviceSession;
+
+import java.net.SocketAddress;
+
+public class TranSyncProtocolDecoder extends BaseProtocolDecoder {
+
+ public TranSyncProtocolDecoder(Protocol protocol) {
+ super(protocol);
+ }
+
+ private String decodeAlarm(int value) {
+ switch (value) {
+ case 4:
+ return Position.ALARM_LOW_BATTERY;
+ case 6:
+ return Position.ALARM_POWER_RESTORED;
+ case 10:
+ return Position.ALARM_SOS;
+ case 13:
+ return Position.ALARM_BRAKING;
+ case 14:
+ return Position.ALARM_ACCELERATION;
+ case 17:
+ return Position.ALARM_OVERSPEED;
+ case 23:
+ return Position.ALARM_ACCIDENT;
+ default:
+ return null;
+ }
+ }
+
+ @Override
+ protected Object decode(Channel channel, SocketAddress remoteAddress, Object msg) throws Exception {
+
+ ByteBuf buf = (ByteBuf) msg;
+
+ buf.readUnsignedShort(); // header
+ buf.readByte(); // length
+
+ int lac = buf.readUnsignedShort();
+
+ String deviceId = ByteBufUtil.hexDump(buf.readSlice(8));
+ DeviceSession deviceSession = getDeviceSession(channel, remoteAddress, deviceId);
+ if (deviceSession == null) {
+ return null;
+ }
+
+ Position position = new Position(getProtocolName());
+ position.setDeviceId(deviceSession.getDeviceId());
+
+ buf.readUnsignedShort(); // index
+ buf.readUnsignedByte(); // type
+
+ position.setTime(new DateBuilder()
+ .setDate(buf.readUnsignedByte(), buf.readUnsignedByte(), buf.readUnsignedByte())
+ .setTime(buf.readUnsignedByte(), buf.readUnsignedByte(), buf.readUnsignedByte())
+ .getDate());
+
+ double latitude = buf.readUnsignedInt() / 1800000.0;
+ double longitude = buf.readUnsignedInt() / 1800000.0;
+
+ position.setSpeed(UnitsConverter.knotsFromKph(buf.readUnsignedByte()));
+ position.setCourse(buf.readUnsignedShort());
+
+ int mnc = buf.readUnsignedByte();
+ int cid = buf.readUnsignedShort();
+ int status0 = buf.readUnsignedByte();
+
+ position.setValid(BitUtil.check(status0, 0));
+ position.setLatitude(BitUtil.check(status0, 1) ? latitude : -latitude);
+ position.setLongitude(BitUtil.check(status0, 2) ? longitude : -longitude);
+
+ position.set(Position.PREFIX_OUT + 1, BitUtil.check(status0, 7));
+ position.set(Position.PREFIX_OUT + 2, BitUtil.check(status0, 6));
+ position.set(Position.PREFIX_IN + 3, BitUtil.check(status0, 5));
+ if (BitUtil.check(status0, 4)) {
+ position.set(Position.KEY_ALARM, Position.ALARM_POWER_OFF);
+ }
+ position.set(Position.KEY_IGNITION, BitUtil.check(status0, 3));
+
+ buf.readUnsignedByte(); // reserved
+
+ int event = buf.readUnsignedByte();
+ position.set(Position.KEY_ALARM, decodeAlarm(event));
+ position.set(Position.KEY_EVENT, event);
+
+ int status3 = buf.readUnsignedByte();
+ if (BitUtil.check(status3, 7)) {
+ position.set(Position.KEY_ARCHIVE, true);
+ }
+ if (BitUtil.check(status3, 5)) {
+ position.set(Position.KEY_ALARM, Position.ALARM_GPS_ANTENNA_CUT);
+ }
+
+ int rssi = buf.readUnsignedByte();
+ CellTower cellTower = CellTower.fromLacCid(getConfig(), lac, cid);
+ cellTower.setMobileNetworkCode(mnc);
+ cellTower.setSignalStrength(rssi);
+ position.setNetwork(new Network(cellTower));
+
+ position.set(Position.KEY_BATTERY, (double) (buf.readUnsignedByte() / 10));
+ position.set(Position.KEY_SATELLITES, buf.readUnsignedByte());
+ position.set(Position.KEY_HDOP, buf.readUnsignedByte());
+ position.set(Position.PREFIX_ADC + 1, (short) buf.readUnsignedShort());
+
+ if (buf.readableBytes() > 5) {
+ buf.readUnsignedByte(); // odometer id
+ int length = buf.readUnsignedByte();
+ if (length > 0) {
+ position.set(Position.KEY_ODOMETER, buf.readBytes(length).readInt());
+ }
+ }
+ if (buf.readableBytes() > 5) {
+ buf.readUnsignedByte(); // rfid id
+ int length = buf.readUnsignedByte();
+ if (length > 0) {
+ position.set(Position.KEY_DRIVER_UNIQUE_ID, ByteBufUtil.hexDump(buf.readSlice(length)));
+ }
+ }
+ if (buf.readableBytes() > 5) {
+ buf.readUnsignedByte(); // adc2 id
+ int length = buf.readUnsignedByte();
+ if (length > 0) {
+ position.set(Position.PREFIX_ADC + 2, buf.readUnsignedShort());
+ }
+ }
+ if (buf.readableBytes() > 5) {
+ buf.readUnsignedByte(); // adc3 id
+ int length = buf.readUnsignedByte();
+ if (length > 0 && length <= buf.readableBytes() - 2) {
+ position.set(Position.PREFIX_ADC + 3, buf.readUnsignedShort());
+ }
+ }
+
+ return position;
+ }
+
+}
diff --git a/src/main/java/org/traccar/protocol/TrvProtocol.java b/src/main/java/org/traccar/protocol/TrvProtocol.java
index e67afbda2..7bdf3d2d0 100644
--- a/src/main/java/org/traccar/protocol/TrvProtocol.java
+++ b/src/main/java/org/traccar/protocol/TrvProtocol.java
@@ -23,7 +23,7 @@ import org.traccar.PipelineBuilder;
import org.traccar.TrackerServer;
import org.traccar.config.Config;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class TrvProtocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/TrvProtocolDecoder.java b/src/main/java/org/traccar/protocol/TrvProtocolDecoder.java
index 9df29ae1b..02744f8ab 100644
--- a/src/main/java/org/traccar/protocol/TrvProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/TrvProtocolDecoder.java
@@ -64,10 +64,20 @@ public class TrvProtocolDecoder extends BaseProtocolDecoder {
.number("(d+),") // mnc
.number("(d+),") // lac
.number("(d+)") // cell
+ .groupBegin()
+ .text(",")
+ .expression("(")
+ .groupBegin()
+ .expression("[^\\|]+") // name
+ .number("|xx-xx-xx-xx-xx-xx") // mac
+ .number("|d+&?") // signal
+ .groupEnd("+")
+ .expression(")")
+ .groupEnd("?")
.any()
.compile();
- private static final Pattern PATTERN_HEATRBEAT = new PatternBuilder()
+ private static final Pattern PATTERN_HEARTBEAT = new PatternBuilder()
.expression("[A-Z]{2,3}")
.text("CP01,")
.number("(ddd)") // gsm
@@ -130,6 +140,16 @@ public class TrvProtocolDecoder extends BaseProtocolDecoder {
}
}
+ private void decodeWifi(Network network, String data) {
+ for (String wifi : data.split("&")) {
+ if (!wifi.isEmpty()) {
+ String[] values = wifi.split("\\|");
+ network.addWifiAccessPoint(WifiAccessPoint.from(
+ values[1].replace('-', ':'), Integer.parseInt(values[2])));
+ }
+ }
+ }
+
@Override
protected Object decode(
Channel channel, SocketAddress remoteAddress, Object msg) throws Exception {
@@ -163,7 +183,7 @@ public class TrvProtocolDecoder extends BaseProtocolDecoder {
if (type.equals("CP01")) {
- Parser parser = new Parser(PATTERN_HEATRBEAT, sentence);
+ Parser parser = new Parser(PATTERN_HEARTBEAT, sentence);
if (!parser.matches()) {
return null;
}
@@ -208,8 +228,16 @@ public class TrvProtocolDecoder extends BaseProtocolDecoder {
decodeCommon(position, parser);
- position.setNetwork(new Network(CellTower.from(
- parser.nextInt(), parser.nextInt(), parser.nextInt(), parser.nextInt())));
+ Network network = new Network();
+
+ network.addCellTower(CellTower.from(
+ parser.nextInt(), parser.nextInt(), parser.nextInt(), parser.nextInt()));
+
+ if (parser.hasNext()) {
+ decodeWifi(network, parser.next());
+ }
+
+ position.setNetwork(network);
return position;
@@ -241,12 +269,7 @@ public class TrvProtocolDecoder extends BaseProtocolDecoder {
}
}
- for (String wifi : parser.next().split("&")) {
- if (!wifi.isEmpty()) {
- String[] values = wifi.split("\\|");
- network.addWifiAccessPoint(WifiAccessPoint.from(values[1], Integer.parseInt(values[2])));
- }
- }
+ decodeWifi(network, parser.next());
position.setNetwork(network);
diff --git a/src/main/java/org/traccar/protocol/Tt8850Protocol.java b/src/main/java/org/traccar/protocol/Tt8850Protocol.java
index ab109e274..8e2800d90 100644
--- a/src/main/java/org/traccar/protocol/Tt8850Protocol.java
+++ b/src/main/java/org/traccar/protocol/Tt8850Protocol.java
@@ -23,7 +23,7 @@ import org.traccar.PipelineBuilder;
import org.traccar.TrackerServer;
import org.traccar.config.Config;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class Tt8850Protocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/TytanProtocol.java b/src/main/java/org/traccar/protocol/TytanProtocol.java
index cc3bc9b52..4fd3c807f 100644
--- a/src/main/java/org/traccar/protocol/TytanProtocol.java
+++ b/src/main/java/org/traccar/protocol/TytanProtocol.java
@@ -20,7 +20,7 @@ import org.traccar.PipelineBuilder;
import org.traccar.TrackerServer;
import org.traccar.config.Config;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class TytanProtocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/TzoneProtocol.java b/src/main/java/org/traccar/protocol/TzoneProtocol.java
index d25757b63..2df721049 100644
--- a/src/main/java/org/traccar/protocol/TzoneProtocol.java
+++ b/src/main/java/org/traccar/protocol/TzoneProtocol.java
@@ -21,7 +21,7 @@ import org.traccar.PipelineBuilder;
import org.traccar.TrackerServer;
import org.traccar.config.Config;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class TzoneProtocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/TzoneProtocolDecoder.java b/src/main/java/org/traccar/protocol/TzoneProtocolDecoder.java
index 8e84a6781..f0b1e709d 100644
--- a/src/main/java/org/traccar/protocol/TzoneProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/TzoneProtocolDecoder.java
@@ -204,30 +204,39 @@ public class TzoneProtocolDecoder extends BaseProtocolDecoder {
}
- private void decodeTags(Position position, ByteBuf buf) {
+ private void decodeTags(Position position, ByteBuf buf, int hardware) {
int blockLength = buf.readUnsignedShort();
int blockEnd = buf.readerIndex() + blockLength;
if (blockLength > 0) {
- buf.readUnsignedByte(); // tag type
+ int type = buf.readUnsignedByte();
- int count = buf.readUnsignedByte();
- int tagLength = buf.readUnsignedByte();
+ if (hardware != 0x153 || type >= 2) {
- for (int i = 1; i <= count; i++) {
- int tagEnd = buf.readerIndex() + tagLength;
+ int count = buf.readUnsignedByte();
+ int tagLength = buf.readUnsignedByte();
+
+ for (int i = 1; i <= count; i++) {
+ int tagEnd = buf.readerIndex() + tagLength;
+
+ buf.readUnsignedByte(); // status
+ buf.readUnsignedShortLE(); // battery voltage
- buf.readUnsignedByte(); // status
- buf.readUnsignedShortLE(); // battery voltage
+ position.set(Position.PREFIX_TEMP + i, (buf.readShortLE() & 0x3fff) * 0.1);
+
+ buf.readUnsignedByte(); // humidity
+ buf.readUnsignedByte(); // rssi
+
+ buf.readerIndex(tagEnd);
+ }
- position.set(Position.PREFIX_TEMP + i, (buf.readShortLE() & 0x3fff) * 0.1);
+ } else if (type == 1) {
- buf.readUnsignedByte(); // humidity
- buf.readUnsignedByte(); // rssi
+ position.set(Position.KEY_CARD, buf.readCharSequence(
+ blockEnd - buf.readerIndex(), StandardCharsets.UTF_8).toString());
- buf.readerIndex(tagEnd);
}
}
@@ -364,9 +373,9 @@ public class TzoneProtocolDecoder extends BaseProtocolDecoder {
}
- if (hardware == 0x406) {
+ if (hardware == 0x153 || hardware == 0x406) {
- decodeTags(position, buf);
+ decodeTags(position, buf, hardware);
}
diff --git a/src/main/java/org/traccar/protocol/UlbotechProtocol.java b/src/main/java/org/traccar/protocol/UlbotechProtocol.java
index 57fc47644..f8c4f1960 100644
--- a/src/main/java/org/traccar/protocol/UlbotechProtocol.java
+++ b/src/main/java/org/traccar/protocol/UlbotechProtocol.java
@@ -21,7 +21,7 @@ import org.traccar.TrackerServer;
import org.traccar.config.Config;
import org.traccar.model.Command;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class UlbotechProtocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/UproProtocol.java b/src/main/java/org/traccar/protocol/UproProtocol.java
index e27088594..cbec9777d 100644
--- a/src/main/java/org/traccar/protocol/UproProtocol.java
+++ b/src/main/java/org/traccar/protocol/UproProtocol.java
@@ -22,7 +22,7 @@ import org.traccar.PipelineBuilder;
import org.traccar.TrackerServer;
import org.traccar.config.Config;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class UproProtocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/UproProtocolDecoder.java b/src/main/java/org/traccar/protocol/UproProtocolDecoder.java
index ed714e464..8d2e5de0a 100644
--- a/src/main/java/org/traccar/protocol/UproProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/UproProtocolDecoder.java
@@ -310,6 +310,10 @@ public class UproProtocolDecoder extends BaseProtocolDecoder {
position.set("serial", data.toString(StandardCharsets.US_ASCII).substring(3));
}
break;
+ case 'd':
+ position.set(Position.PREFIX_ADC + 1,
+ Integer.parseInt(data.toString(StandardCharsets.US_ASCII)) / 100.0);
+ break;
default:
break;
}
diff --git a/src/main/java/org/traccar/protocol/UuxProtocol.java b/src/main/java/org/traccar/protocol/UuxProtocol.java
index 3de4a4732..63727cb94 100644
--- a/src/main/java/org/traccar/protocol/UuxProtocol.java
+++ b/src/main/java/org/traccar/protocol/UuxProtocol.java
@@ -21,7 +21,7 @@ import org.traccar.PipelineBuilder;
import org.traccar.TrackerServer;
import org.traccar.config.Config;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class UuxProtocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/V680Protocol.java b/src/main/java/org/traccar/protocol/V680Protocol.java
index 53bca849c..587a0c8f7 100644
--- a/src/main/java/org/traccar/protocol/V680Protocol.java
+++ b/src/main/java/org/traccar/protocol/V680Protocol.java
@@ -23,7 +23,7 @@ import org.traccar.PipelineBuilder;
import org.traccar.TrackerServer;
import org.traccar.config.Config;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class V680Protocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/ValtrackProtocol.java b/src/main/java/org/traccar/protocol/ValtrackProtocol.java
new file mode 100644
index 000000000..8471a0fd8
--- /dev/null
+++ b/src/main/java/org/traccar/protocol/ValtrackProtocol.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2024 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.http.HttpObjectAggregator;
+import io.netty.handler.codec.http.HttpRequestDecoder;
+import io.netty.handler.codec.http.HttpResponseEncoder;
+import jakarta.inject.Inject;
+import org.traccar.BaseProtocol;
+import org.traccar.PipelineBuilder;
+import org.traccar.TrackerServer;
+import org.traccar.config.Config;
+
+public class ValtrackProtocol extends BaseProtocol {
+
+ @Inject
+ public ValtrackProtocol(Config config) {
+ addServer(new TrackerServer(config, getName(), false) {
+ @Override
+ protected void addProtocolHandlers(PipelineBuilder pipeline, Config config) {
+ pipeline.addLast(new HttpResponseEncoder());
+ pipeline.addLast(new HttpRequestDecoder());
+ pipeline.addLast(new HttpObjectAggregator(16384));
+ pipeline.addLast(new ValtrackProtocolDecoder(ValtrackProtocol.this));
+ }
+ });
+ }
+}
diff --git a/src/main/java/org/traccar/protocol/ValtrackProtocolDecoder.java b/src/main/java/org/traccar/protocol/ValtrackProtocolDecoder.java
new file mode 100644
index 000000000..dc9ca8590
--- /dev/null
+++ b/src/main/java/org/traccar/protocol/ValtrackProtocolDecoder.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright 2024 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 io.netty.handler.codec.http.FullHttpRequest;
+import io.netty.handler.codec.http.HttpResponseStatus;
+import jakarta.json.Json;
+import jakarta.json.JsonArray;
+import jakarta.json.JsonObject;
+import org.traccar.BaseHttpProtocolDecoder;
+import org.traccar.Protocol;
+import org.traccar.model.Position;
+import org.traccar.session.DeviceSession;
+
+import java.io.StringReader;
+import java.net.SocketAddress;
+import java.nio.charset.StandardCharsets;
+import java.util.Date;
+import java.util.LinkedList;
+import java.util.List;
+
+public class ValtrackProtocolDecoder extends BaseHttpProtocolDecoder {
+
+ public ValtrackProtocolDecoder(Protocol protocol) {
+ super(protocol);
+ }
+
+ @Override
+ protected Object decode(
+ Channel channel, SocketAddress remoteAddress, Object msg) throws Exception {
+
+ FullHttpRequest request = (FullHttpRequest) msg;
+ String content = request.content().toString(StandardCharsets.UTF_8);
+ JsonObject object = Json.createReader(new StringReader(content)).readObject();
+ JsonArray messages = object.getJsonArray("resource");
+
+ List<Position> positions = new LinkedList<>();
+ for (int i = 0; i < messages.size(); i++) {
+
+ JsonObject message = messages.getJsonObject(i);
+ String id = message.getString("devid");
+
+ DeviceSession deviceSession = getDeviceSession(channel, remoteAddress, id);
+ if (deviceSession == null) {
+ continue;
+ }
+
+ Position position = new Position(getProtocolName());
+ position.setDeviceId(deviceSession.getDeviceId());
+
+ position.setValid(true);
+ position.setTime(new Date());
+ position.setLatitude(Double.parseDouble(message.getString("lat")));
+ position.setLongitude(Double.parseDouble(message.getString("lon")));
+ String speed = message.getString("speed");
+ if (!speed.isEmpty()) {
+ position.setSpeed(Double.parseDouble(speed));
+ }
+
+ position.set(Position.KEY_BATTERY, Double.parseDouble(message.getString("vbat")));
+
+ positions.add(position);
+
+ }
+
+ sendResponse(channel, HttpResponseStatus.OK);
+ return positions;
+ }
+
+}
diff --git a/src/main/java/org/traccar/protocol/VisiontekProtocol.java b/src/main/java/org/traccar/protocol/VisiontekProtocol.java
index 5296402b4..83bcd37ff 100644
--- a/src/main/java/org/traccar/protocol/VisiontekProtocol.java
+++ b/src/main/java/org/traccar/protocol/VisiontekProtocol.java
@@ -23,7 +23,7 @@ import org.traccar.PipelineBuilder;
import org.traccar.TrackerServer;
import org.traccar.config.Config;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class VisiontekProtocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/VltProtocol.java b/src/main/java/org/traccar/protocol/VltProtocol.java
new file mode 100644
index 000000000..005cd8ffb
--- /dev/null
+++ b/src/main/java/org/traccar/protocol/VltProtocol.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2023 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.http.HttpObjectAggregator;
+import io.netty.handler.codec.http.HttpRequestDecoder;
+import io.netty.handler.codec.http.HttpResponseEncoder;
+import org.traccar.BaseProtocol;
+import org.traccar.PipelineBuilder;
+import org.traccar.TrackerServer;
+import org.traccar.config.Config;
+
+import jakarta.inject.Inject;
+
+public class VltProtocol extends BaseProtocol {
+
+ @Inject
+ public VltProtocol(Config config) {
+ addServer(new TrackerServer(config, getName(), false) {
+ @Override
+ protected void addProtocolHandlers(PipelineBuilder pipeline, Config config) {
+ pipeline.addLast(new HttpResponseEncoder());
+ pipeline.addLast(new HttpRequestDecoder());
+ pipeline.addLast(new HttpObjectAggregator(65535));
+ pipeline.addLast(new VltProtocolDecoder(VltProtocol.this));
+ }
+ });
+ }
+
+}
diff --git a/src/main/java/org/traccar/protocol/VltProtocolDecoder.java b/src/main/java/org/traccar/protocol/VltProtocolDecoder.java
new file mode 100644
index 000000000..01c0563f5
--- /dev/null
+++ b/src/main/java/org/traccar/protocol/VltProtocolDecoder.java
@@ -0,0 +1,139 @@
+/*
+ * Copyright 2023 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 io.netty.handler.codec.http.FullHttpRequest;
+import io.netty.handler.codec.http.HttpResponseStatus;
+import io.netty.handler.codec.http.QueryStringDecoder;
+import org.traccar.BaseHttpProtocolDecoder;
+import org.traccar.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 org.traccar.session.DeviceSession;
+
+import java.net.SocketAddress;
+import java.nio.charset.StandardCharsets;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.regex.Pattern;
+
+public class VltProtocolDecoder extends BaseHttpProtocolDecoder {
+
+ public VltProtocolDecoder(Protocol protocol) {
+ super(protocol);
+ }
+
+ private static final Pattern PATTERN = new PatternBuilder()
+ .number("(dd)") // alert id
+ .expression("([HL])") // history
+ .number("([01])") // validity
+ .number("(dd)(dd)(dd)") // date (ddmmyy)
+ .number("(dd)(dd)(dd)") // time (hhmmss)
+ .number("(d{3}.d{6})([NS])") // latitude
+ .number("(d{3}.d{6})([EW])") // longitude
+ .number("(d{3})") // mcc
+ .expression("(x*[0-9]+)") // mnc
+ .number("(x{4})") // lac
+ .number("(d{9})") // cid
+ .number("(d{3}.d{2})") // speed
+ .number("(d{3}.d{2})") // course
+ .number("(d{2})") // satellites
+ .number("(d{2})") // hdop
+ .number("(d{2})") // rssi
+ .number("([01])") // ignition
+ .number("([01])") // charging
+ .expression("([HMS])") // vehicle mode
+ .compile();
+
+ private Position decodePosition(DeviceSession deviceSession, String sentence) {
+
+ Parser parser = new Parser(PATTERN, sentence);
+ if (!parser.matches()) {
+ return null;
+ }
+
+ Position position = new Position(getProtocolName());
+ position.setDeviceId(deviceSession.getDeviceId());
+
+ position.set(Position.KEY_EVENT, parser.nextInt());
+ position.set(Position.KEY_ARCHIVE, parser.next().equals("H") ? true : null);
+
+ position.setValid(parser.nextInt() > 0);
+ position.setTime(parser.nextDateTime(Parser.DateTimeFormat.DMY_HMS));
+ position.setLatitude(parser.nextCoordinate(Parser.CoordinateFormat.DEG_HEM));
+ position.setLongitude(parser.nextCoordinate(Parser.CoordinateFormat.DEG_HEM));
+
+ int mcc = parser.nextInt();
+ int mnc = Integer.parseInt(parser.next().replaceAll("x", ""));
+ int lac = parser.nextHexInt();
+ int cid = parser.nextInt();
+
+ position.setSpeed(parser.nextDouble());
+ position.setCourse(parser.nextDouble());
+
+ position.set(Position.KEY_SATELLITES, parser.nextInt());
+ position.set(Position.KEY_HDOP, parser.nextInt());
+
+ position.setNetwork(new Network(CellTower.from(mcc, mnc, lac, cid, parser.nextInt())));
+
+ position.set(Position.KEY_IGNITION, parser.nextInt() > 0);
+ position.set(Position.KEY_CHARGE, parser.nextInt() > 0);
+ position.set(Position.KEY_MOTION, parser.next().equals("M"));
+
+ return position;
+ }
+
+ @Override
+ protected Object decode(
+ Channel channel, SocketAddress remoteAddress, Object msg) throws Exception {
+
+ FullHttpRequest request = (FullHttpRequest) msg;
+ QueryStringDecoder decoder = new QueryStringDecoder(
+ request.content().toString(StandardCharsets.US_ASCII), false);
+ String sentence = decoder.parameters().get("vltdata").iterator().next();
+
+ int index = 0;
+ String type = sentence.substring(index, index += 3);
+ String imei = sentence.substring(index, index += 15);
+
+ DeviceSession deviceSession = getDeviceSession(channel, remoteAddress, imei);
+ if (deviceSession == null) {
+ sendResponse(channel, HttpResponseStatus.BAD_REQUEST);
+ return null;
+ }
+
+ sendResponse(channel, HttpResponseStatus.OK);
+
+ switch (type) {
+ case "NRM":
+ return decodePosition(deviceSession, sentence.substring(3 + 15));
+ case "BTH":
+ List<Position> positions = new LinkedList<>();
+ int count = Integer.parseInt(sentence.substring(index, index += 3));
+ for (int i = 0; i < count; i++) {
+ positions.add(decodePosition(deviceSession, sentence.substring(index, index += 78)));
+ }
+ return positions;
+ default:
+ return null;
+ }
+ }
+
+}
diff --git a/src/main/java/org/traccar/protocol/VnetProtocol.java b/src/main/java/org/traccar/protocol/VnetProtocol.java
index dd739f0d9..6ccc54483 100644
--- a/src/main/java/org/traccar/protocol/VnetProtocol.java
+++ b/src/main/java/org/traccar/protocol/VnetProtocol.java
@@ -23,7 +23,7 @@ import org.traccar.config.Config;
import java.nio.ByteOrder;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class VnetProtocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/Vt200Protocol.java b/src/main/java/org/traccar/protocol/Vt200Protocol.java
index efb5fe2fd..97e64b74f 100644
--- a/src/main/java/org/traccar/protocol/Vt200Protocol.java
+++ b/src/main/java/org/traccar/protocol/Vt200Protocol.java
@@ -20,7 +20,7 @@ import org.traccar.PipelineBuilder;
import org.traccar.TrackerServer;
import org.traccar.config.Config;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class Vt200Protocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/Vt200ProtocolDecoder.java b/src/main/java/org/traccar/protocol/Vt200ProtocolDecoder.java
index a8fc801e7..1ad15f39c 100644
--- a/src/main/java/org/traccar/protocol/Vt200ProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/Vt200ProtocolDecoder.java
@@ -123,7 +123,7 @@ public class Vt200ProtocolDecoder extends BaseProtocolDecoder {
position.set("tripStart", decodeDate(buf).getTime());
position.set("tripEnd", decodeDate(buf).getTime());
- position.set("drivingTime", buf.readUnsignedShort());
+ position.set(Position.KEY_DRIVING_TIME, buf.readUnsignedShort());
position.set(Position.KEY_FUEL_CONSUMPTION, buf.readUnsignedInt());
position.set(Position.KEY_ODOMETER_TRIP, buf.readUnsignedInt());
diff --git a/src/main/java/org/traccar/protocol/VtfmsProtocol.java b/src/main/java/org/traccar/protocol/VtfmsProtocol.java
index 482ab4a37..91453c413 100644
--- a/src/main/java/org/traccar/protocol/VtfmsProtocol.java
+++ b/src/main/java/org/traccar/protocol/VtfmsProtocol.java
@@ -21,7 +21,7 @@ import org.traccar.PipelineBuilder;
import org.traccar.TrackerServer;
import org.traccar.config.Config;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class VtfmsProtocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/WatchFrameDecoder.java b/src/main/java/org/traccar/protocol/WatchFrameDecoder.java
index f99bd52e2..9dfae8726 100644
--- a/src/main/java/org/traccar/protocol/WatchFrameDecoder.java
+++ b/src/main/java/org/traccar/protocol/WatchFrameDecoder.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2017 - 2018 Anton Tananaev (anton@traccar.org)
+ * Copyright 2017 - 2023 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.
@@ -27,7 +27,26 @@ public class WatchFrameDecoder extends BaseFrameDecoder {
protected Object decode(
ChannelHandlerContext ctx, Channel channel, ByteBuf buf) throws Exception {
- int endIndex = buf.indexOf(buf.readerIndex(), buf.writerIndex(), (byte) ']') + 1;
+ int brackets = 0;
+ int endIndex = -1;
+ for (int i = buf.readerIndex(); i < buf.writerIndex(); i++) {
+ byte b = buf.getByte(i);
+ switch (b) {
+ case '[':
+ brackets += 1;
+ break;
+ case ']':
+ brackets -= 1;
+ break;
+ default:
+ break;
+ }
+ if (brackets == 0 && i > buf.readerIndex()) {
+ endIndex = i + 1;
+ break;
+ }
+ }
+
if (endIndex > 0) {
ByteBuf frame = Unpooled.buffer();
while (buf.readerIndex() < endIndex) {
diff --git a/src/main/java/org/traccar/protocol/WatchProtocol.java b/src/main/java/org/traccar/protocol/WatchProtocol.java
index 600f81328..aee70b6ec 100644
--- a/src/main/java/org/traccar/protocol/WatchProtocol.java
+++ b/src/main/java/org/traccar/protocol/WatchProtocol.java
@@ -21,7 +21,7 @@ import org.traccar.TrackerServer;
import org.traccar.config.Config;
import org.traccar.model.Command;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class WatchProtocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/WatchProtocolDecoder.java b/src/main/java/org/traccar/protocol/WatchProtocolDecoder.java
index 40d56b130..b586f4e92 100644
--- a/src/main/java/org/traccar/protocol/WatchProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/WatchProtocolDecoder.java
@@ -51,7 +51,7 @@ public class WatchProtocolDecoder extends BaseProtocolDecoder {
.number("(dd)(dd)(dd),") // time (hhmmss)
.expression("([AV]),") // validity
.number(" *(-?d+.d+),") // latitude
- .expression("([NS]),")
+ .expression("([NS])?,")
.number(" *(-?d+.d+),") // longitude
.expression("([EW])?,")
.number("(d+.?d*),") // speed
@@ -285,7 +285,8 @@ public class WatchProtocolDecoder extends BaseProtocolDecoder {
|| type.equalsIgnoreCase("BLOOD")
|| type.equalsIgnoreCase("BPHRT")
|| type.equalsIgnoreCase("TEMP")
- || type.equalsIgnoreCase("btemp2")) {
+ || type.equalsIgnoreCase("btemp2")
+ || type.equalsIgnoreCase("oxygen")) {
if (buf.isReadable()) {
@@ -303,6 +304,8 @@ public class WatchProtocolDecoder extends BaseProtocolDecoder {
if (Integer.parseInt(values[valueIndex++]) > 0) {
position.set(Position.PREFIX_TEMP + 1, Double.parseDouble(values[valueIndex]));
}
+ } else if (type.equalsIgnoreCase("oxygen")) {
+ position.set("bloodOxygen", Integer.parseInt(values[++valueIndex]));
} else {
if (type.equalsIgnoreCase("BPHRT") || type.equalsIgnoreCase("BLOOD")) {
position.set("pressureHigh", values[valueIndex++]);
diff --git a/src/main/java/org/traccar/protocol/WialonProtocol.java b/src/main/java/org/traccar/protocol/WialonProtocol.java
index a744349cd..84033132d 100644
--- a/src/main/java/org/traccar/protocol/WialonProtocol.java
+++ b/src/main/java/org/traccar/protocol/WialonProtocol.java
@@ -27,7 +27,7 @@ import org.traccar.model.Command;
import java.nio.charset.StandardCharsets;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class WialonProtocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/WialonProtocolDecoder.java b/src/main/java/org/traccar/protocol/WialonProtocolDecoder.java
index 3d57525b7..4d1b34dba 100644
--- a/src/main/java/org/traccar/protocol/WialonProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/WialonProtocolDecoder.java
@@ -63,8 +63,9 @@ public class WialonProtocolDecoder extends BaseProtocolDecoder {
.number("(?:NA|(d+));") // outputs
.expression("(?:NA|([^;]*));") // adc
.expression("(?:NA|([^;]*));") // ibutton
- .expression("(?:NA|(.*))") // params
+ .expression("(?:NA|([^;]*))") // params
.groupEnd("?")
+ .any()
.compile();
private void sendResponse(Channel channel, SocketAddress remoteAddress, String type, Integer number) {
@@ -101,7 +102,7 @@ public class WialonProtocolDecoder extends BaseProtocolDecoder {
position.setTime(new Date());
}
- if (parser.hasNext(9)) {
+ if (parser.hasNextAny(9)) {
position.setLatitude(parser.nextCoordinate());
position.setLongitude(parser.nextCoordinate());
position.setSpeed(UnitsConverter.knotsFromKph(parser.nextDouble(0)));
@@ -135,10 +136,22 @@ public class WialonProtocolDecoder extends BaseProtocolDecoder {
for (String param : values) {
Matcher paramParser = Pattern.compile("(.*):[1-3]:(.*)").matcher(param);
if (paramParser.matches()) {
+ String key = paramParser.group(1).toLowerCase();
+ String value = paramParser.group(2);
try {
- position.set(paramParser.group(1).toLowerCase(), Double.parseDouble(paramParser.group(2)));
+ if (key.equals("accuracy")) {
+ position.setAccuracy(Double.parseDouble(value));
+ } else {
+ position.set(key, Double.parseDouble(value));
+ }
} catch (NumberFormatException e) {
- position.set(paramParser.group(1).toLowerCase(), paramParser.group(2));
+ if (value.equalsIgnoreCase("true")) {
+ position.set(key, true);
+ } else if (value.equalsIgnoreCase("false")) {
+ position.set(key, false);
+ } else {
+ position.set(key, value);
+ }
}
}
}
diff --git a/src/main/java/org/traccar/protocol/WliProtocol.java b/src/main/java/org/traccar/protocol/WliProtocol.java
index f7084e55b..5b9ebb520 100644
--- a/src/main/java/org/traccar/protocol/WliProtocol.java
+++ b/src/main/java/org/traccar/protocol/WliProtocol.java
@@ -20,7 +20,7 @@ import org.traccar.PipelineBuilder;
import org.traccar.TrackerServer;
import org.traccar.config.Config;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class WliProtocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/WondexProtocol.java b/src/main/java/org/traccar/protocol/WondexProtocol.java
index 5a0401df4..e27b8e2bb 100644
--- a/src/main/java/org/traccar/protocol/WondexProtocol.java
+++ b/src/main/java/org/traccar/protocol/WondexProtocol.java
@@ -22,7 +22,7 @@ import org.traccar.TrackerServer;
import org.traccar.config.Config;
import org.traccar.model.Command;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class WondexProtocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/WristbandProtocol.java b/src/main/java/org/traccar/protocol/WristbandProtocol.java
index c5d8d4050..117daf8cf 100644
--- a/src/main/java/org/traccar/protocol/WristbandProtocol.java
+++ b/src/main/java/org/traccar/protocol/WristbandProtocol.java
@@ -21,7 +21,7 @@ import org.traccar.PipelineBuilder;
import org.traccar.TrackerServer;
import org.traccar.config.Config;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class WristbandProtocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/Xexun2Protocol.java b/src/main/java/org/traccar/protocol/Xexun2Protocol.java
index 52cf731f0..9dd517cfa 100644
--- a/src/main/java/org/traccar/protocol/Xexun2Protocol.java
+++ b/src/main/java/org/traccar/protocol/Xexun2Protocol.java
@@ -21,7 +21,7 @@ import org.traccar.TrackerServer;
import org.traccar.config.Config;
import org.traccar.model.Command;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class Xexun2Protocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/Xexun2ProtocolDecoder.java b/src/main/java/org/traccar/protocol/Xexun2ProtocolDecoder.java
index 913dfaf28..0e3c44e12 100644
--- a/src/main/java/org/traccar/protocol/Xexun2ProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/Xexun2ProtocolDecoder.java
@@ -156,7 +156,7 @@ public class Xexun2ProtocolDecoder extends BaseProtocolDecoder {
for (int j = 0; j < wifiCount; j++) {
String mac = ByteBufUtil.hexDump(buf.readSlice(6)).replaceAll("(..)", "$1:");
network.addWifiAccessPoint(WifiAccessPoint.from(
- mac.substring(0, mac.length() - 1), buf.readUnsignedByte()));
+ mac.substring(0, mac.length() - 1), buf.readByte()));
}
}
if (BitUtil.check(positionMask, 2)) {
@@ -164,7 +164,7 @@ public class Xexun2ProtocolDecoder extends BaseProtocolDecoder {
for (int j = 0; j < cellCount; j++) {
network.addCellTower(CellTower.from(
buf.readUnsignedShort(), buf.readUnsignedShort(),
- buf.readInt(), buf.readUnsignedInt(), buf.readUnsignedByte()));
+ buf.readInt(), buf.readUnsignedInt(), buf.readByte()));
}
}
if (network.getWifiAccessPoints() != null || network.getCellTowers() != null) {
diff --git a/src/main/java/org/traccar/protocol/XexunProtocol.java b/src/main/java/org/traccar/protocol/XexunProtocol.java
index 5c7329603..e76e47d19 100644
--- a/src/main/java/org/traccar/protocol/XexunProtocol.java
+++ b/src/main/java/org/traccar/protocol/XexunProtocol.java
@@ -25,7 +25,7 @@ import org.traccar.config.Config;
import org.traccar.config.Keys;
import org.traccar.model.Command;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class XexunProtocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/XirgoProtocol.java b/src/main/java/org/traccar/protocol/XirgoProtocol.java
index 0841d86d5..7e14c6842 100644
--- a/src/main/java/org/traccar/protocol/XirgoProtocol.java
+++ b/src/main/java/org/traccar/protocol/XirgoProtocol.java
@@ -24,7 +24,7 @@ import org.traccar.TrackerServer;
import org.traccar.config.Config;
import org.traccar.model.Command;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class XirgoProtocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/Xrb28Protocol.java b/src/main/java/org/traccar/protocol/Xrb28Protocol.java
index 65c2a1230..135fb0928 100644
--- a/src/main/java/org/traccar/protocol/Xrb28Protocol.java
+++ b/src/main/java/org/traccar/protocol/Xrb28Protocol.java
@@ -26,7 +26,7 @@ import org.traccar.model.Command;
import java.nio.charset.StandardCharsets;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class Xrb28Protocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/Xrb28ProtocolDecoder.java b/src/main/java/org/traccar/protocol/Xrb28ProtocolDecoder.java
index 88f2d07e5..6033293c4 100644
--- a/src/main/java/org/traccar/protocol/Xrb28ProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/Xrb28ProtocolDecoder.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2018 Anton Tananaev (anton@traccar.org)
+ * Copyright 2018 - 2024 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.
@@ -27,6 +27,7 @@ import org.traccar.model.Command;
import org.traccar.model.Position;
import java.net.SocketAddress;
+import java.util.Arrays;
import java.util.regex.Pattern;
public class Xrb28ProtocolDecoder extends BaseProtocolDecoder {
@@ -46,6 +47,7 @@ public class Xrb28ProtocolDecoder extends BaseProtocolDecoder {
.expression("....,")
.expression("..,") // vendor
.number("d{15},") // imei
+ .number("d{12},").optional() // time
.expression("..,") // type
.number("[01],") // reserved
.number("(dd)(dd)(dd).d+,") // time (hhmmss)
@@ -67,23 +69,44 @@ public class Xrb28ProtocolDecoder extends BaseProtocolDecoder {
Channel channel, SocketAddress remoteAddress, Object msg) throws Exception {
String sentence = (String) msg;
+ String[] values = sentence.replaceAll("#$", "").split(",");
- DeviceSession deviceSession = getDeviceSession(channel, remoteAddress, sentence.substring(9, 24));
+ int index = 0;
+ String header = values[index++];
+ String vendor = values[index++];
+
+ String imei = values[index++];
+ DeviceSession deviceSession = getDeviceSession(channel, remoteAddress, imei);
if (deviceSession == null) {
return null;
}
- String type = sentence.substring(25, 27);
+ String time;
+ if (values[index].length() == 12) {
+ time = values[index++];
+ } else {
+ time = null;
+ }
+
+ String type = values[index++];
if (channel != null) {
+ StringBuilder response = new StringBuilder("\u00ff\u00ff");
+ response.append(header.replaceAll("R$", "S")).append(',');
+ response.append(vendor).append(',');
+ response.append(imei).append(',');
+ if (time != null) {
+ response.append(time).append(',');
+ }
if (type.matches("L0|L1|W0|E1")) {
- channel.write(new NetworkMessage(
- "\u00ff\u00ff*SCOS" + sentence.substring(5, 27) + "#\n",
- remoteAddress));
+ response.append(type).append("#\n");
+ channel.write(new NetworkMessage(response.toString(), remoteAddress));
} else if (type.equals("R0") && pendingCommand != null) {
- String command = pendingCommand.equals(Command.TYPE_ALARM_ARM) ? "L1," : "L0,";
- channel.write(new NetworkMessage(
- "\u00ff\u00ff*SCOS" + sentence.substring(5, 25) + command + sentence.substring(30) + "\n",
- remoteAddress));
+ String command = pendingCommand.equals(Command.TYPE_ALARM_ARM) ? "L1" : "L0";
+ response.append(command);
+ String[] remaining = Arrays.copyOfRange(values, index, values.length);
+ response.append(String.join(",", remaining));
+ response.append("#\n");
+ channel.write(new NetworkMessage(response.toString(), remoteAddress));
pendingCommand = null;
}
}
@@ -95,11 +118,6 @@ public class Xrb28ProtocolDecoder extends BaseProtocolDecoder {
getLastLocation(position, null);
- String payload = sentence.substring(25, sentence.length() - 1);
-
- int index = 0;
- String[] values = payload.substring(3).split(",");
-
switch (type) {
case "Q0":
position.set(Position.KEY_BATTERY, Integer.parseInt(values[index++]) * 0.01);
@@ -146,7 +164,8 @@ public class Xrb28ProtocolDecoder extends BaseProtocolDecoder {
case "K0":
case "I0":
case "M0":
- position.set(Position.KEY_RESULT, payload);
+ String[] remaining = Arrays.copyOfRange(values, index, values.length);
+ position.set(Position.KEY_RESULT, String.join(",", remaining));
break;
default:
break;
diff --git a/src/main/java/org/traccar/protocol/Xt013Protocol.java b/src/main/java/org/traccar/protocol/Xt013Protocol.java
index 9e9087609..25809463a 100644
--- a/src/main/java/org/traccar/protocol/Xt013Protocol.java
+++ b/src/main/java/org/traccar/protocol/Xt013Protocol.java
@@ -23,7 +23,7 @@ import org.traccar.PipelineBuilder;
import org.traccar.TrackerServer;
import org.traccar.config.Config;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class Xt013Protocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/Xt2400Protocol.java b/src/main/java/org/traccar/protocol/Xt2400Protocol.java
index e200adb9f..1b7fc840b 100644
--- a/src/main/java/org/traccar/protocol/Xt2400Protocol.java
+++ b/src/main/java/org/traccar/protocol/Xt2400Protocol.java
@@ -20,7 +20,7 @@ import org.traccar.PipelineBuilder;
import org.traccar.TrackerServer;
import org.traccar.config.Config;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class Xt2400Protocol extends BaseProtocol {
diff --git a/src/main/java/org/traccar/protocol/Xt2400ProtocolDecoder.java b/src/main/java/org/traccar/protocol/Xt2400ProtocolDecoder.java
index edcb3f535..11f9e0654 100644
--- a/src/main/java/org/traccar/protocol/Xt2400ProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/Xt2400ProtocolDecoder.java
@@ -177,7 +177,7 @@ public class Xt2400ProtocolDecoder extends BaseProtocolDecoder {
position.set(Position.KEY_POWER, buf.readUnsignedByte() * 0.1);
break;
case 0x57:
- position.set(Position.KEY_OBD_SPEED, UnitsConverter.knotsFromKph(buf.readUnsignedShort()));
+ position.set(Position.KEY_OBD_SPEED, buf.readUnsignedShort());
break;
case 0x65:
position.set(Position.KEY_VIN, buf.readSlice(17).toString(StandardCharsets.US_ASCII));
diff --git a/src/main/java/org/traccar/protocol/YwtProtocol.java b/src/main/java/org/traccar/protocol/YwtProtocol.java
index fb44e2360..27c71cfa8 100644
--- a/src/main/java/org/traccar/protocol/YwtProtocol.java
+++ b/src/main/java/org/traccar/protocol/YwtProtocol.java
@@ -23,7 +23,7 @@ import org.traccar.PipelineBuilder;
import org.traccar.TrackerServer;
import org.traccar.config.Config;
-import javax.inject.Inject;
+import jakarta.inject.Inject;
public class YwtProtocol extends BaseProtocol {