Implement Aquila track protocol

This commit is contained in:
Anton Tananaev 2015-09-24 14:56:35 +12:00
parent a3f912fc98
commit 85bb659197
6 changed files with 244 additions and 0 deletions

View File

@ -336,5 +336,6 @@
<entry key='castel.port'>5086</entry>
<entry key='mxt.port'>5087</entry>
<entry key='cityeasy.port'>5088</entry>
<entry key='aquila.port'>5089</entry>
</properties>

View File

@ -0,0 +1,41 @@
/*
* Copyright 2015 Anton Tananaev (anton.tananaev@gmail.com)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.traccar.helper;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;
public class PatternUtil {
public static String checkPattern(String pattern, String input) {
String match = null;
for (int i = 0; i < pattern.length(); i++) {
try {
Matcher matcher = Pattern.compile(pattern.substring(0, i) + ".*").matcher(input);
if (matcher.matches()) {
match = pattern.substring(0, i);
}
} catch (PatternSyntaxException e) {
}
}
return match;
}
}

View File

@ -0,0 +1,45 @@
/*
* Copyright 2015 Anton Tananaev (anton.tananaev@gmail.com)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.traccar.protocol;
import org.jboss.netty.bootstrap.ServerBootstrap;
import org.jboss.netty.channel.ChannelPipeline;
import org.jboss.netty.handler.codec.frame.LineBasedFrameDecoder;
import org.jboss.netty.handler.codec.string.StringDecoder;
import org.traccar.BaseProtocol;
import org.traccar.TrackerServer;
import java.util.List;
public class AquilaProtocol extends BaseProtocol {
public AquilaProtocol() {
super("aquila");
}
@Override
public void initTrackerServers(List<TrackerServer> serverList) {
serverList.add(new TrackerServer(new ServerBootstrap(), this.getName()) {
@Override
protected void addSpecificHandlers(ChannelPipeline pipeline) {
pipeline.addLast("frameDecoder", new LineBasedFrameDecoder(1024));
pipeline.addLast("stringDecoder", new StringDecoder());
pipeline.addLast("objectDecoder", new AquilaProtocolDecoder(AquilaProtocol.this));
}
});
}
}

View File

@ -0,0 +1,116 @@
/*
* Copyright 2015 Anton Tananaev (anton.tananaev@gmail.com)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.traccar.protocol;
import org.jboss.netty.channel.Channel;
import org.traccar.BaseProtocolDecoder;
import org.traccar.helper.UnitsConverter;
import org.traccar.model.Event;
import org.traccar.model.Position;
import java.net.SocketAddress;
import java.util.Calendar;
import java.util.TimeZone;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class AquilaProtocolDecoder extends BaseProtocolDecoder {
public AquilaProtocolDecoder(AquilaProtocol protocol) {
super(protocol);
}
private static final Pattern pattern = Pattern.compile(
"\\$\\$" +
"CLIENT_[^,]+," + // IMEI
"(\\d+)," + // Device serial number
"(\\d+)," + // Event
"(-?\\d+\\.\\d+)," + // Latitude
"(-?\\d+\\.\\d+)," + // Longitude
"(\\d{2})(\\d{2})(\\d{2})" + // Date (YYMMDD)
"(\\d{2})(\\d{2})(\\d{2})," + // Time (HHMMSS)
"([AV])," + // Validity
"(\\d+)," + // GSM
"(\\d+)," + // Speed
"\\d+," + // Driver code
"(\\d+)," + // Fuel
"(\\d+)," + // IO 1
"[01]," + // Case open switch
"[01]," + // Over speed start
"[01]," + // Over speed end
"0,0,0," + // Reserved
"([01])," + // Power status
"([01])," + // IO 2
"0," + // Reserved
"([01])," + // Ignition
"[01]," + // Ignition off event
".*");
@Override
protected Object decode(
Channel channel, SocketAddress remoteAddress, Object msg)
throws Exception {
String sentence = (String) msg;
Matcher parser = pattern.matcher(sentence);
if (!parser.matches()) {
return null;
}
Position position = new Position();
position.setProtocol(getProtocolName());
Integer index = 1;
String id = parser.group(index++);
if (!identify(id, channel)) {
return null;
}
position.setDeviceId(getDeviceId());
position.set(Event.KEY_EVENT, Integer.parseInt(parser.group(index++)));
position.setLatitude(Double.parseDouble(parser.group(index++)));
position.setLongitude(Double.parseDouble(parser.group(index++)));
Calendar time = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
time.clear();
time.set(Calendar.YEAR, 2000 + Integer.parseInt(parser.group(index++)));
time.set(Calendar.MONTH, Integer.parseInt(parser.group(index++)) - 1);
time.set(Calendar.DAY_OF_MONTH, Integer.parseInt(parser.group(index++)));
time.set(Calendar.HOUR_OF_DAY, Integer.parseInt(parser.group(index++)));
time.set(Calendar.MINUTE, Integer.parseInt(parser.group(index++)));
time.set(Calendar.SECOND, Integer.parseInt(parser.group(index++)));
position.setTime(time.getTime());
position.setValid(parser.group(index++).equals("A"));
position.set(Event.KEY_GSM, Integer.parseInt(parser.group(index++)));
position.setSpeed(UnitsConverter.knotsFromKph(Double.parseDouble(parser.group(index++))));
position.set(Event.KEY_FUEL, parser.group(index++));
position.set(Event.PREFIX_IO + 1, parser.group(index++));
position.set(Event.KEY_CHARGE, parser.group(index++));
position.set(Event.PREFIX_IO + 2, parser.group(index++));
position.set(Event.KEY_IGNITION, parser.group(index++).equals("1"));
return position;
}
}

View File

@ -0,0 +1,16 @@
package org.traccar.helper;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
public class PatternUtilTest {
@Test
public void testCheckPattern() {
assertEquals("ab", PatternUtil.checkPattern("abc", "abd"));
}
}

View File

@ -0,0 +1,25 @@
package org.traccar.protocol;
import org.junit.Test;
import static org.traccar.helper.DecoderVerifier.verify;
public class AquilaProtocolDecoderTest extends ProtocolDecoderTest {
@Test
public void testDecode() throws Exception {
AquilaProtocolDecoder decoder = new AquilaProtocolDecoder(new AquilaProtocol());
verify(decoder.decode(null, null,
"$$CLIENT_1ZF,130329214,1,12.962985,77.576484,140127165433,A,22,0,0,1,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,*26"));
verify(decoder.decode(null, null,
"$$CLIENT_1WP,141216511,3,12.963123,77.534012,150908163534,A,31,0,0,0,7,0,0,0,0,0,0,0,1,0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1,1,1,0,*28"));
verify(decoder.decode(null, null,
"$$CLIENT_1WP,141216511,3,12.963212,77.533989,150908164041,V,31,0,0,0,8,0,0,0,0,0,0,0,1,0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1,1,1,0,*2A"));
}
}