From abfedde2e0fc8b4128639263944ad88c40fee12a Mon Sep 17 00:00:00 2001 From: Anton Tananaev Date: Sun, 12 Nov 2017 12:49:27 +1300 Subject: Support OKO NAVI protocol (fix #1612) --- setup/default.xml | 1 + 1 file changed, 1 insertion(+) (limited to 'setup/default.xml') diff --git a/setup/default.xml b/setup/default.xml index 8752432c6..7caa1d32a 100644 --- a/setup/default.xml +++ b/setup/default.xml @@ -220,5 +220,6 @@ 5149 5150 5151 + 5152 -- cgit v1.2.3 From e2f36439c120c3dd951e66a43739359751adc9fc Mon Sep 17 00:00:00 2001 From: Anton Tananaev Date: Mon, 13 Nov 2017 06:07:08 +1300 Subject: Implement IVT 401 protocol --- setup/default.xml | 1 + src/org/traccar/protocol/Avt401Protocol.java | 45 ++++++++++ .../traccar/protocol/Avt401ProtocolDecoder.java | 97 ++++++++++++++++++++++ .../protocol/Avt401ProtocolDecoderTest.java | 33 ++++++++ 4 files changed, 176 insertions(+) create mode 100644 src/org/traccar/protocol/Avt401Protocol.java create mode 100644 src/org/traccar/protocol/Avt401ProtocolDecoder.java create mode 100644 test/org/traccar/protocol/Avt401ProtocolDecoderTest.java (limited to 'setup/default.xml') diff --git a/setup/default.xml b/setup/default.xml index 7caa1d32a..6d8bd278f 100644 --- a/setup/default.xml +++ b/setup/default.xml @@ -221,5 +221,6 @@ 5150 5151 5152 + 5153 diff --git a/src/org/traccar/protocol/Avt401Protocol.java b/src/org/traccar/protocol/Avt401Protocol.java new file mode 100644 index 000000000..e4a7e3df6 --- /dev/null +++ b/src/org/traccar/protocol/Avt401Protocol.java @@ -0,0 +1,45 @@ +/* + * Copyright 2017 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 org.jboss.netty.bootstrap.ServerBootstrap; +import org.jboss.netty.channel.ChannelPipeline; +import org.jboss.netty.handler.codec.string.StringDecoder; +import org.traccar.BaseProtocol; +import org.traccar.CharacterDelimiterFrameDecoder; +import org.traccar.TrackerServer; + +import java.util.List; + +public class Avt401Protocol extends BaseProtocol { + + public Avt401Protocol() { + super("avt401"); + } + + @Override + public void initTrackerServers(List serverList) { + serverList.add(new TrackerServer(new ServerBootstrap(), getName()) { + @Override + protected void addSpecificHandlers(ChannelPipeline pipeline) { + pipeline.addLast("frameDecoder", new CharacterDelimiterFrameDecoder(1024, ';')); + pipeline.addLast("stringDecoder", new StringDecoder()); + pipeline.addLast("objectDecoder", new Avt401ProtocolDecoder(Avt401Protocol.this)); + } + }); + } + +} diff --git a/src/org/traccar/protocol/Avt401ProtocolDecoder.java b/src/org/traccar/protocol/Avt401ProtocolDecoder.java new file mode 100644 index 000000000..5918b54a1 --- /dev/null +++ b/src/org/traccar/protocol/Avt401ProtocolDecoder.java @@ -0,0 +1,97 @@ +/* + * Copyright 2017 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 org.jboss.netty.channel.Channel; +import org.traccar.BaseProtocolDecoder; +import org.traccar.DeviceSession; +import org.traccar.helper.Parser; +import org.traccar.helper.PatternBuilder; +import org.traccar.helper.UnitsConverter; +import org.traccar.model.Position; + +import java.net.SocketAddress; +import java.util.regex.Pattern; + +public class Avt401ProtocolDecoder extends BaseProtocolDecoder { + + public Avt401ProtocolDecoder(Avt401Protocol protocol) { + super(protocol); + } + + private static final Pattern PATTERN = new PatternBuilder() + .text("(") + .expression("TL[ABLN],") // header + .number("(d+),") // imei + .number("(dd)(dd)(dd),") // date (ddmmyy) + .number("(dd)(dd)(dd),") // time (hhmmss) + .number("([-+]d+.d+),") // longitude + .number("([-+]d+.d+),") // latitude + .number("(d+),") // speed + .number("(d+),") // course + .number("(-?d+.?d*),") // altitude + .number("(d+),") // satellites + .number("(d),") // gps status + .number("(d+),") // rssi + .number("(d+),") // input + .number("(d+),") // output + .number("(d+.d+),") // adc + .number("(d+.d+),") // power + .number("(d+.d+),") // battery + .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(); + position.setProtocol(getProtocolName()); + position.setDeviceId(deviceSession.getDeviceId()); + + position.setTime(parser.nextDateTime(Parser.DateTimeFormat.DMY_HMS)); + + position.setLongitude(parser.nextDouble()); + position.setLatitude(parser.nextDouble()); + position.setSpeed(UnitsConverter.knotsFromKph(parser.nextInt())); + position.setCourse(parser.nextInt()); + position.setAltitude(parser.nextDouble()); + + position.set(Position.KEY_SATELLITES, parser.nextInt()); + + position.setValid(parser.nextInt() > 0); + + position.set(Position.KEY_RSSI, parser.nextInt()); + position.set(Position.KEY_INPUT, parser.nextBinInt()); + position.set(Position.KEY_OUTPUT, parser.nextBinInt()); + position.set(Position.PREFIX_ADC + 1, parser.nextDouble()); + position.set(Position.KEY_POWER, parser.nextDouble()); + position.set(Position.KEY_BATTERY, parser.nextDouble()); + + return position; + } + +} diff --git a/test/org/traccar/protocol/Avt401ProtocolDecoderTest.java b/test/org/traccar/protocol/Avt401ProtocolDecoderTest.java new file mode 100644 index 000000000..37b60d977 --- /dev/null +++ b/test/org/traccar/protocol/Avt401ProtocolDecoderTest.java @@ -0,0 +1,33 @@ +package org.traccar.protocol; + +import org.junit.Test; +import org.traccar.ProtocolTest; + +public class Avt401ProtocolDecoderTest extends ProtocolTest { + + @Test + public void testDecode() throws Exception { + + Avt401ProtocolDecoder decoder = new Avt401ProtocolDecoder(new Avt401Protocol()); + + verifyPosition(decoder, text( + "(TLN,356917050291991,090315,133525,+12.990582,+77.589080,0,0,944,13,1,5,000,00,0.00,10.88,6.31,29.55,0.00,0,0.99,66,0,0,88,95)")); + + verifyPosition(decoder, text( + "(TLN,356917050269732,061117,220046,+21.134126,+74.798561,51,28,204,14,1,5,100,00,0.0,13.92,7.82,23.74,0.0,1,1.33,-9,0,429,4848,67)")); + + verifyPosition(decoder, text( + "(TLN,356917050269732,061117,220116,+21.137619,+74.800659,52,28,202,14,1,3,100,00,0.0,13.92,7.82,23.74,0.0,1,1.26,-23,0,445,4849,125)")); + + verifyPosition(decoder, text( + "(TLA,356917050217335,190115,011336,+12.932403,+79.898887,0,0,71.7,08,3,10,000,00,0.00,10.41,7.07,26.84,0.00,0,0.99,63,0,0,0,0,0,0,000000000,0,0,0,0,0,0,0,2,0,0,14,86)")); + + verifyPosition(decoder, text( + "(TLB,356917050291991,090315,133525,+12.990582,+77.589080,0,0,944,13,1,5,000,00,0.00,10.88,6.31,29.55,0.00,0,0.99,66,0,0,88,95)")); + + verifyPosition(decoder, text( + "(TLL,356917050217335,190115,011336,+12.932403,+79.898887,0,0,71.7,08,3,10,000,00,0.00,10.41,7.07,26.84,0.00,0,0.99,63,0,0,0,0,0,0,000000000,0,0,0,0,0,0,0,2,0,0,14,86)")); + + } + +} -- cgit v1.2.3 From e6e762c1c9416cf52421d0b26dbd38f2b70e2c3f Mon Sep 17 00:00:00 2001 From: Anton Tananaev Date: Tue, 14 Nov 2017 01:35:15 +1300 Subject: Fix typo in protocol name --- setup/default.xml | 2 +- src/org/traccar/protocol/Avt401Protocol.java | 45 ---------- .../traccar/protocol/Avt401ProtocolDecoder.java | 97 ---------------------- src/org/traccar/protocol/Ivt401Protocol.java | 45 ++++++++++ .../traccar/protocol/Ivt401ProtocolDecoder.java | 97 ++++++++++++++++++++++ .../protocol/Avt401ProtocolDecoderTest.java | 33 -------- .../protocol/Ivt401ProtocolDecoderTest.java | 33 ++++++++ 7 files changed, 176 insertions(+), 176 deletions(-) delete mode 100644 src/org/traccar/protocol/Avt401Protocol.java delete mode 100644 src/org/traccar/protocol/Avt401ProtocolDecoder.java create mode 100644 src/org/traccar/protocol/Ivt401Protocol.java create mode 100644 src/org/traccar/protocol/Ivt401ProtocolDecoder.java delete mode 100644 test/org/traccar/protocol/Avt401ProtocolDecoderTest.java create mode 100644 test/org/traccar/protocol/Ivt401ProtocolDecoderTest.java (limited to 'setup/default.xml') diff --git a/setup/default.xml b/setup/default.xml index 6d8bd278f..1d6775731 100644 --- a/setup/default.xml +++ b/setup/default.xml @@ -221,6 +221,6 @@ 5150 5151 5152 - 5153 + 5153 diff --git a/src/org/traccar/protocol/Avt401Protocol.java b/src/org/traccar/protocol/Avt401Protocol.java deleted file mode 100644 index e4a7e3df6..000000000 --- a/src/org/traccar/protocol/Avt401Protocol.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright 2017 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 org.jboss.netty.bootstrap.ServerBootstrap; -import org.jboss.netty.channel.ChannelPipeline; -import org.jboss.netty.handler.codec.string.StringDecoder; -import org.traccar.BaseProtocol; -import org.traccar.CharacterDelimiterFrameDecoder; -import org.traccar.TrackerServer; - -import java.util.List; - -public class Avt401Protocol extends BaseProtocol { - - public Avt401Protocol() { - super("avt401"); - } - - @Override - public void initTrackerServers(List serverList) { - serverList.add(new TrackerServer(new ServerBootstrap(), getName()) { - @Override - protected void addSpecificHandlers(ChannelPipeline pipeline) { - pipeline.addLast("frameDecoder", new CharacterDelimiterFrameDecoder(1024, ';')); - pipeline.addLast("stringDecoder", new StringDecoder()); - pipeline.addLast("objectDecoder", new Avt401ProtocolDecoder(Avt401Protocol.this)); - } - }); - } - -} diff --git a/src/org/traccar/protocol/Avt401ProtocolDecoder.java b/src/org/traccar/protocol/Avt401ProtocolDecoder.java deleted file mode 100644 index 5918b54a1..000000000 --- a/src/org/traccar/protocol/Avt401ProtocolDecoder.java +++ /dev/null @@ -1,97 +0,0 @@ -/* - * Copyright 2017 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 org.jboss.netty.channel.Channel; -import org.traccar.BaseProtocolDecoder; -import org.traccar.DeviceSession; -import org.traccar.helper.Parser; -import org.traccar.helper.PatternBuilder; -import org.traccar.helper.UnitsConverter; -import org.traccar.model.Position; - -import java.net.SocketAddress; -import java.util.regex.Pattern; - -public class Avt401ProtocolDecoder extends BaseProtocolDecoder { - - public Avt401ProtocolDecoder(Avt401Protocol protocol) { - super(protocol); - } - - private static final Pattern PATTERN = new PatternBuilder() - .text("(") - .expression("TL[ABLN],") // header - .number("(d+),") // imei - .number("(dd)(dd)(dd),") // date (ddmmyy) - .number("(dd)(dd)(dd),") // time (hhmmss) - .number("([-+]d+.d+),") // longitude - .number("([-+]d+.d+),") // latitude - .number("(d+),") // speed - .number("(d+),") // course - .number("(-?d+.?d*),") // altitude - .number("(d+),") // satellites - .number("(d),") // gps status - .number("(d+),") // rssi - .number("(d+),") // input - .number("(d+),") // output - .number("(d+.d+),") // adc - .number("(d+.d+),") // power - .number("(d+.d+),") // battery - .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(); - position.setProtocol(getProtocolName()); - position.setDeviceId(deviceSession.getDeviceId()); - - position.setTime(parser.nextDateTime(Parser.DateTimeFormat.DMY_HMS)); - - position.setLongitude(parser.nextDouble()); - position.setLatitude(parser.nextDouble()); - position.setSpeed(UnitsConverter.knotsFromKph(parser.nextInt())); - position.setCourse(parser.nextInt()); - position.setAltitude(parser.nextDouble()); - - position.set(Position.KEY_SATELLITES, parser.nextInt()); - - position.setValid(parser.nextInt() > 0); - - position.set(Position.KEY_RSSI, parser.nextInt()); - position.set(Position.KEY_INPUT, parser.nextBinInt()); - position.set(Position.KEY_OUTPUT, parser.nextBinInt()); - position.set(Position.PREFIX_ADC + 1, parser.nextDouble()); - position.set(Position.KEY_POWER, parser.nextDouble()); - position.set(Position.KEY_BATTERY, parser.nextDouble()); - - return position; - } - -} diff --git a/src/org/traccar/protocol/Ivt401Protocol.java b/src/org/traccar/protocol/Ivt401Protocol.java new file mode 100644 index 000000000..b58601ba1 --- /dev/null +++ b/src/org/traccar/protocol/Ivt401Protocol.java @@ -0,0 +1,45 @@ +/* + * Copyright 2017 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 org.jboss.netty.bootstrap.ServerBootstrap; +import org.jboss.netty.channel.ChannelPipeline; +import org.jboss.netty.handler.codec.string.StringDecoder; +import org.traccar.BaseProtocol; +import org.traccar.CharacterDelimiterFrameDecoder; +import org.traccar.TrackerServer; + +import java.util.List; + +public class Ivt401Protocol extends BaseProtocol { + + public Ivt401Protocol() { + super("ivt401"); + } + + @Override + public void initTrackerServers(List serverList) { + serverList.add(new TrackerServer(new ServerBootstrap(), getName()) { + @Override + protected void addSpecificHandlers(ChannelPipeline pipeline) { + pipeline.addLast("frameDecoder", new CharacterDelimiterFrameDecoder(1024, ';')); + pipeline.addLast("stringDecoder", new StringDecoder()); + pipeline.addLast("objectDecoder", new Ivt401ProtocolDecoder(Ivt401Protocol.this)); + } + }); + } + +} diff --git a/src/org/traccar/protocol/Ivt401ProtocolDecoder.java b/src/org/traccar/protocol/Ivt401ProtocolDecoder.java new file mode 100644 index 000000000..c42f9fcc0 --- /dev/null +++ b/src/org/traccar/protocol/Ivt401ProtocolDecoder.java @@ -0,0 +1,97 @@ +/* + * Copyright 2017 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 org.jboss.netty.channel.Channel; +import org.traccar.BaseProtocolDecoder; +import org.traccar.DeviceSession; +import org.traccar.helper.Parser; +import org.traccar.helper.PatternBuilder; +import org.traccar.helper.UnitsConverter; +import org.traccar.model.Position; + +import java.net.SocketAddress; +import java.util.regex.Pattern; + +public class Ivt401ProtocolDecoder extends BaseProtocolDecoder { + + public Ivt401ProtocolDecoder(Ivt401Protocol protocol) { + super(protocol); + } + + private static final Pattern PATTERN = new PatternBuilder() + .text("(") + .expression("TL[ABLN],") // header + .number("(d+),") // imei + .number("(dd)(dd)(dd),") // date (ddmmyy) + .number("(dd)(dd)(dd),") // time (hhmmss) + .number("([-+]d+.d+),") // longitude + .number("([-+]d+.d+),") // latitude + .number("(d+),") // speed + .number("(d+),") // course + .number("(-?d+.?d*),") // altitude + .number("(d+),") // satellites + .number("(d),") // gps status + .number("(d+),") // rssi + .number("(d+),") // input + .number("(d+),") // output + .number("(d+.d+),") // adc + .number("(d+.d+),") // power + .number("(d+.d+),") // battery + .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(); + position.setProtocol(getProtocolName()); + position.setDeviceId(deviceSession.getDeviceId()); + + position.setTime(parser.nextDateTime(Parser.DateTimeFormat.DMY_HMS)); + + position.setLongitude(parser.nextDouble()); + position.setLatitude(parser.nextDouble()); + position.setSpeed(UnitsConverter.knotsFromKph(parser.nextInt())); + position.setCourse(parser.nextInt()); + position.setAltitude(parser.nextDouble()); + + position.set(Position.KEY_SATELLITES, parser.nextInt()); + + position.setValid(parser.nextInt() > 0); + + position.set(Position.KEY_RSSI, parser.nextInt()); + position.set(Position.KEY_INPUT, parser.nextBinInt()); + position.set(Position.KEY_OUTPUT, parser.nextBinInt()); + position.set(Position.PREFIX_ADC + 1, parser.nextDouble()); + position.set(Position.KEY_POWER, parser.nextDouble()); + position.set(Position.KEY_BATTERY, parser.nextDouble()); + + return position; + } + +} diff --git a/test/org/traccar/protocol/Avt401ProtocolDecoderTest.java b/test/org/traccar/protocol/Avt401ProtocolDecoderTest.java deleted file mode 100644 index 37b60d977..000000000 --- a/test/org/traccar/protocol/Avt401ProtocolDecoderTest.java +++ /dev/null @@ -1,33 +0,0 @@ -package org.traccar.protocol; - -import org.junit.Test; -import org.traccar.ProtocolTest; - -public class Avt401ProtocolDecoderTest extends ProtocolTest { - - @Test - public void testDecode() throws Exception { - - Avt401ProtocolDecoder decoder = new Avt401ProtocolDecoder(new Avt401Protocol()); - - verifyPosition(decoder, text( - "(TLN,356917050291991,090315,133525,+12.990582,+77.589080,0,0,944,13,1,5,000,00,0.00,10.88,6.31,29.55,0.00,0,0.99,66,0,0,88,95)")); - - verifyPosition(decoder, text( - "(TLN,356917050269732,061117,220046,+21.134126,+74.798561,51,28,204,14,1,5,100,00,0.0,13.92,7.82,23.74,0.0,1,1.33,-9,0,429,4848,67)")); - - verifyPosition(decoder, text( - "(TLN,356917050269732,061117,220116,+21.137619,+74.800659,52,28,202,14,1,3,100,00,0.0,13.92,7.82,23.74,0.0,1,1.26,-23,0,445,4849,125)")); - - verifyPosition(decoder, text( - "(TLA,356917050217335,190115,011336,+12.932403,+79.898887,0,0,71.7,08,3,10,000,00,0.00,10.41,7.07,26.84,0.00,0,0.99,63,0,0,0,0,0,0,000000000,0,0,0,0,0,0,0,2,0,0,14,86)")); - - verifyPosition(decoder, text( - "(TLB,356917050291991,090315,133525,+12.990582,+77.589080,0,0,944,13,1,5,000,00,0.00,10.88,6.31,29.55,0.00,0,0.99,66,0,0,88,95)")); - - verifyPosition(decoder, text( - "(TLL,356917050217335,190115,011336,+12.932403,+79.898887,0,0,71.7,08,3,10,000,00,0.00,10.41,7.07,26.84,0.00,0,0.99,63,0,0,0,0,0,0,000000000,0,0,0,0,0,0,0,2,0,0,14,86)")); - - } - -} diff --git a/test/org/traccar/protocol/Ivt401ProtocolDecoderTest.java b/test/org/traccar/protocol/Ivt401ProtocolDecoderTest.java new file mode 100644 index 000000000..c0f076014 --- /dev/null +++ b/test/org/traccar/protocol/Ivt401ProtocolDecoderTest.java @@ -0,0 +1,33 @@ +package org.traccar.protocol; + +import org.junit.Test; +import org.traccar.ProtocolTest; + +public class Ivt401ProtocolDecoderTest extends ProtocolTest { + + @Test + public void testDecode() throws Exception { + + Ivt401ProtocolDecoder decoder = new Ivt401ProtocolDecoder(new Ivt401Protocol()); + + verifyPosition(decoder, text( + "(TLN,356917050291991,090315,133525,+12.990582,+77.589080,0,0,944,13,1,5,000,00,0.00,10.88,6.31,29.55,0.00,0,0.99,66,0,0,88,95)")); + + verifyPosition(decoder, text( + "(TLN,356917050269732,061117,220046,+21.134126,+74.798561,51,28,204,14,1,5,100,00,0.0,13.92,7.82,23.74,0.0,1,1.33,-9,0,429,4848,67)")); + + verifyPosition(decoder, text( + "(TLN,356917050269732,061117,220116,+21.137619,+74.800659,52,28,202,14,1,3,100,00,0.0,13.92,7.82,23.74,0.0,1,1.26,-23,0,445,4849,125)")); + + verifyPosition(decoder, text( + "(TLA,356917050217335,190115,011336,+12.932403,+79.898887,0,0,71.7,08,3,10,000,00,0.00,10.41,7.07,26.84,0.00,0,0.99,63,0,0,0,0,0,0,000000000,0,0,0,0,0,0,0,2,0,0,14,86)")); + + verifyPosition(decoder, text( + "(TLB,356917050291991,090315,133525,+12.990582,+77.589080,0,0,944,13,1,5,000,00,0.00,10.88,6.31,29.55,0.00,0,0.99,66,0,0,88,95)")); + + verifyPosition(decoder, text( + "(TLL,356917050217335,190115,011336,+12.932403,+79.898887,0,0,71.7,08,3,10,000,00,0.00,10.41,7.07,26.84,0.00,0,0.99,63,0,0,0,0,0,0,000000000,0,0,0,0,0,0,0,2,0,0,14,86)")); + + } + +} -- cgit v1.2.3 From e0f16f7f797a3ce1bfae3be2625690ad4b048240 Mon Sep 17 00:00:00 2001 From: Abyss777 Date: Tue, 14 Nov 2017 12:44:59 +0500 Subject: Improve LDAP --- setup/default.xml | 2 +- src/org/traccar/Context.java | 2 +- src/org/traccar/database/DataManager.java | 11 ++- src/org/traccar/database/LdapProvider.java | 143 +++++++++++++++++++++++++++-- 4 files changed, 142 insertions(+), 16 deletions(-) (limited to 'setup/default.xml') diff --git a/setup/default.xml b/setup/default.xml index 6d8bd278f..bb51472c1 100644 --- a/setup/default.xml +++ b/setup/default.xml @@ -35,7 +35,7 @@ SELECT * FROM users - WHERE email = :email + WHERE email = :email OR login = :email diff --git a/src/org/traccar/Context.java b/src/org/traccar/Context.java index 9a48b2740..511ec980e 100644 --- a/src/org/traccar/Context.java +++ b/src/org/traccar/Context.java @@ -329,7 +329,7 @@ public final class Context { } if (config.getBoolean("ldap.enable")) { - ldapProvider = new LdapProvider(config.getString("ldap.url"), config.getString("ldap.context")); + ldapProvider = new LdapProvider(config); } if (config.hasKey("media.path")) { diff --git a/src/org/traccar/database/DataManager.java b/src/org/traccar/database/DataManager.java index f71e3e538..abc424ff9 100644 --- a/src/org/traccar/database/DataManager.java +++ b/src/org/traccar/database/DataManager.java @@ -76,9 +76,13 @@ public class DataManager { private boolean generateQueries; + private boolean forceLdap; + public DataManager(Config config) throws Exception { this.config = config; + forceLdap = config.getBoolean("ldap.force"); + initDatabase(); initDatabaseSchema(); } @@ -304,15 +308,12 @@ public class DataManager { LdapProvider ldapProvider = Context.getLdapProvider(); if (user != null) { if (ldapProvider != null && ldapProvider.login(user.getLogin(), password) - || user.isPasswordValid(password)) { + || !forceLdap && user.isPasswordValid(password)) { return user; } } else { if (ldapProvider != null && ldapProvider.login(email, password)) { - user = new User(); - user.setName(email); - user.setEmail(email); - user.setLogin(email); + user = ldapProvider.getUser(email); Context.getUsersManager().addItem(user); return user; } diff --git a/src/org/traccar/database/LdapProvider.java b/src/org/traccar/database/LdapProvider.java index 6a4c244f8..b193b87c1 100644 --- a/src/org/traccar/database/LdapProvider.java +++ b/src/org/traccar/database/LdapProvider.java @@ -16,36 +16,161 @@ package org.traccar.database; import javax.naming.Context; +import javax.naming.NamingEnumeration; import javax.naming.NamingException; +import javax.naming.directory.Attribute; import javax.naming.directory.InitialDirContext; +import javax.naming.directory.SearchControls; +import javax.naming.directory.SearchResult; + +import org.traccar.Config; +import org.traccar.helper.Log; +import org.traccar.model.User; + import java.util.Hashtable; public class LdapProvider { private String url; - private String context; + private String searchBase; + private String idAttribute; + private String nameAttribute; + private String mailAttribute; + private String searchFilter; + private String adminFilter; + private String serviceUser; + private String servicePassword; - public LdapProvider(String url, String context) { - this.url = url; - this.context = context; + public LdapProvider(Config config) { + String url = config.getString("ldap.url"); + if (url != null) { + this.url = url; + } else { + this.url = "ldap://" + config.getString("ldap.server") + ":" + config.getInteger("ldap.port", 389); + } + this.searchBase = config.getString("ldap.base"); + this.idAttribute = config.getString("ldap.idAttribute", "uid"); + this.nameAttribute = config.getString("ldap.nameAttribute", "cn"); + this.mailAttribute = config.getString("ldap.mailAttribute", "mail"); + this.searchFilter = config.getString("ldap.searchFilter", "(" + idAttribute + "=:login)"); + String adminGroup = config.getString("ldap.adminGroup"); + this.adminFilter = config.getString("ldap.adminFilter"); + if (this.adminFilter == null && adminGroup != null) { + this.adminFilter = "(&(" + idAttribute + "=:login)(memberOf=" + adminGroup + "))"; + } + this.serviceUser = config.getString("ldap.user"); + this.servicePassword = config.getString("ldap.password"); } - public boolean login(String username, String password) { - + private InitialDirContext auth(String accountName, String password) throws NamingException { Hashtable env = new Hashtable<>(); env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory"); env.put(Context.PROVIDER_URL, url); env.put(Context.SECURITY_AUTHENTICATION, "simple"); - env.put(Context.SECURITY_PRINCIPAL, "uid=" + username + "," + context); + env.put(Context.SECURITY_PRINCIPAL, accountName); env.put(Context.SECURITY_CREDENTIALS, password); + return new InitialDirContext(env); + } + + private boolean isAdmin(String accountName) { + if (this.adminFilter != null) { + try { + InitialDirContext context = initContext(); + String searchString = new String(adminFilter).replace(":login", accountName); + SearchControls searchControls = new SearchControls(); + searchControls.setSearchScope(SearchControls.SUBTREE_SCOPE); + NamingEnumeration results = context.search(searchBase, searchString, searchControls); + if (results.hasMoreElements()) { + results.nextElement(); + if (results.hasMoreElements()) { + Log.warning("Matched multiple users for the accountName: " + accountName); + return false; + } + return true; + } + } catch (NamingException e) { + return false; + } + } + return false; + } + + public InitialDirContext initContext() throws NamingException { + return auth(serviceUser, servicePassword); + } + + private SearchResult lookupUser(String accountName) throws NamingException { + InitialDirContext context = initContext(); + + String searchString = new String(searchFilter).replace(":login", accountName); + + SearchControls searchControls = new SearchControls(); + String[] attributeFilter = {idAttribute, nameAttribute, mailAttribute}; + searchControls.setReturningAttributes(attributeFilter); + searchControls.setSearchScope(SearchControls.SUBTREE_SCOPE); + + NamingEnumeration results = context.search(searchBase, searchString, searchControls); + + SearchResult searchResult = null; + if (results.hasMoreElements()) { + searchResult = (SearchResult) results.nextElement(); + if (results.hasMoreElements()) { + Log.warning("Matched multiple users for the accountName: " + accountName); + return null; + } + } + + return searchResult; + } + + public User getUser(String accountName) { + SearchResult ldapUser; + User user = new User(); + try { + ldapUser = lookupUser(accountName); + if (ldapUser != null) { + Attribute attribute = ldapUser.getAttributes().get(idAttribute); + if (attribute != null) { + user.setLogin((String) attribute.get()); + } else { + user.setLogin(accountName); + } + attribute = ldapUser.getAttributes().get(nameAttribute); + if (attribute != null) { + user.setName((String) attribute.get()); + } else { + user.setName(accountName); + } + attribute = ldapUser.getAttributes().get(mailAttribute); + if (attribute != null) { + user.setEmail((String) attribute.get()); + } else { + user.setEmail(accountName); + } + } + user.setAdmin(isAdmin(accountName)); + } catch (NamingException e) { + user.setLogin(accountName); + user.setName(accountName); + user.setEmail(accountName); + Log.warning(e); + } + return user; + } + + public boolean login(String username, String password) { try { - new InitialDirContext(env).close(); - return true; + SearchResult ldapUser = lookupUser(username); + if (ldapUser != null) { + auth(ldapUser.getNameInNamespace(), password).close(); + return true; + } } catch (NamingException e) { return false; } + return false; } } -- cgit v1.2.3