From bf02ae6cdfc1912e1fe7b87e0790ae89028717f4 Mon Sep 17 00:00:00 2001 From: Anton Tananaev Date: Fri, 10 Feb 2017 05:46:45 +1300 Subject: Refactor Suntech protocol decoder --- .../traccar/protocol/SuntechProtocolDecoder.java | 166 +++++++++++++++------ .../protocol/SuntechProtocolDecoderTest.java | 10 +- 2 files changed, 125 insertions(+), 51 deletions(-) diff --git a/src/org/traccar/protocol/SuntechProtocolDecoder.java b/src/org/traccar/protocol/SuntechProtocolDecoder.java index c9235f47f..d081cb901 100644 --- a/src/org/traccar/protocol/SuntechProtocolDecoder.java +++ b/src/org/traccar/protocol/SuntechProtocolDecoder.java @@ -1,5 +1,5 @@ /* - * Copyright 2013 - 2015 Anton Tananaev (anton@traccar.org) + * Copyright 2013 - 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. @@ -17,85 +17,157 @@ package org.traccar.protocol; import org.jboss.netty.channel.Channel; import org.traccar.BaseProtocolDecoder; +import org.traccar.Context; import org.traccar.DeviceSession; -import org.traccar.helper.DateBuilder; -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; +import java.text.DateFormat; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.TimeZone; public class SuntechProtocolDecoder extends BaseProtocolDecoder { + private int protocolType; + public SuntechProtocolDecoder(SuntechProtocol protocol) { super(protocol); + + protocolType = Context.getConfig().getInteger(getProtocolName() + ".protocolType"); } - private static final Pattern PATTERN = new PatternBuilder() - .expression("S.") - .number("ddd") - .expression("(?:[A-Z]{3})?;") // header - .expression("([^;]+);").optional() // type - .number("(d{6,});") // device id - .number("d+;").optional() - .number("(d+);") // version - .number("(dddd)(dd)(dd);") // date - .number("(dd):(dd):(dd);") // time - .number("(x+);").optional() // cell - .number("([-+]dd.d+);") // latitude - .number("([-+]ddd.d+);") // longitude - .number("(ddd.ddd);") // speed - .number("(ddd.dd);") // course - .number("d+;").optional() - .number("(d+.d+)?") // battery - .any() // full format - .compile(); + public void setProtocolType(int protocolType) { + this.protocolType = protocolType; + } - @Override - protected Object decode( - Channel channel, SocketAddress remoteAddress, Object msg) throws Exception { + private Position decode9( + Channel channel, SocketAddress remoteAddress, String[] values) throws ParseException { + int index = 1; + + String type = values[index++]; + + if (!type.equals("Location") && !type.equals("Emergency") && !type.equals("Alert")) { + return null; + } + + Position position = new Position(); + position.setProtocol(getProtocolName()); + + if (type.equals("Emergency") || type.equals("Alert")) { + position.set(Position.KEY_ALARM, Position.ALARM_GENERAL); + } + + DeviceSession deviceSession = getDeviceSession(channel, remoteAddress, values[index++]); + if (deviceSession == null) { + return null; + } + position.setDeviceId(deviceSession.getDeviceId()); + + position.set(Position.KEY_VERSION, values[index++]); + + DateFormat dateFormat = new SimpleDateFormat("yyyyMMddHH:mm:ss"); + dateFormat.setTimeZone(TimeZone.getTimeZone("UTC")); + position.setTime(dateFormat.parse(values[index++] + values[index++])); + + if (protocolType == 1) { + index += 1; // cell + } + + 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.setValid(values[index++].equals("1")); + + if (protocolType == 1) { + position.set(Position.KEY_ODOMETER, Integer.parseInt(values[index])); + } + + return position; + } - Parser parser = new Parser(PATTERN, (String) msg); - if (!parser.matches()) { + private Position decode23( + Channel channel, SocketAddress remoteAddress, String protocol, String[] values) throws ParseException { + int index = 0; + + String type = values[index++].substring(5); + + if (!type.equals("STT") && !type.equals("EMG") && !type.equals("EVT") && !type.equals("ALT")) { return null; } Position position = new Position(); position.setProtocol(getProtocolName()); - if (parser.hasNext()) { - String type = parser.next(); - if (type.equals("Alert") || type.equals("Emergency")) { - position.set(Position.KEY_ALARM, Position.ALARM_GENERAL); - } + if (type.equals("EMG") || type.equals("ALT")) { + position.set(Position.KEY_ALARM, Position.ALARM_GENERAL); } - DeviceSession deviceSession = getDeviceSession(channel, remoteAddress, parser.next()); + DeviceSession deviceSession = getDeviceSession(channel, remoteAddress, values[index++]); if (deviceSession == null) { return null; } position.setDeviceId(deviceSession.getDeviceId()); - position.set(Position.KEY_VERSION, parser.next()); + if (protocol.equals("ST300")) { + index += 1; // model + } + + position.set(Position.KEY_VERSION, values[index++]); + + DateFormat dateFormat = new SimpleDateFormat("yyyyMMddHH:mm:ss"); + dateFormat.setTimeZone(TimeZone.getTimeZone("UTC")); + position.setTime(dateFormat.parse(values[index++] + values[index++])); + + index += 1; // cell + + 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++])); - DateBuilder dateBuilder = new DateBuilder() - .setDate(parser.nextInt(), parser.nextInt(), parser.nextInt()) - .setTime(parser.nextInt(), parser.nextInt(), parser.nextInt()); - position.setTime(dateBuilder.getDate()); + position.set(Position.KEY_SATELLITES, Integer.parseInt(values[index++])); - parser.next(); // location code + bsic + position.setValid(values[index++].equals("1")); - position.setValid(true); - position.setLatitude(parser.nextDouble()); - position.setLongitude(parser.nextDouble()); - position.setSpeed(UnitsConverter.knotsFromKph(parser.nextDouble())); - position.setCourse(parser.nextDouble()); + position.set(Position.KEY_ODOMETER, Integer.parseInt(values[index++])); + position.set(Position.KEY_POWER, Double.parseDouble(values[index++])); - position.set(Position.KEY_BATTERY, parser.next()); + position.set(Position.PREFIX_IO + 1, values[index++]); + + index += 1; // mode + + if (type.equals("STT")) { + position.set(Position.KEY_INDEX, Integer.parseInt(values[index++])); + } + + if (index < values.length) { + position.set(Position.KEY_HOURS, Integer.parseInt(values[index++])); + } + + if (index < values.length) { + position.set(Position.KEY_BATTERY, Double.parseDouble(values[index])); + } return position; } + @Override + protected Object decode( + Channel channel, SocketAddress remoteAddress, Object msg) throws Exception { + + String[] values = ((String) msg).split(";"); + + String protocol = values[0].substring(0, 5); + + if (protocol.equals("ST910")) { + return decode9(channel, remoteAddress, values); + } else { + return decode23(channel, remoteAddress, protocol, values); + } + } + } diff --git a/test/org/traccar/protocol/SuntechProtocolDecoderTest.java b/test/org/traccar/protocol/SuntechProtocolDecoderTest.java index 78e1fb1de..ba2848348 100644 --- a/test/org/traccar/protocol/SuntechProtocolDecoderTest.java +++ b/test/org/traccar/protocol/SuntechProtocolDecoderTest.java @@ -10,9 +10,6 @@ public class SuntechProtocolDecoderTest extends ProtocolTest { SuntechProtocolDecoder decoder = new SuntechProtocolDecoder(new SuntechProtocol()); - verifyPosition(decoder, text( - "ST910;Location;560266;500;20161207;21:33:11;af910be101;-25.504234;-049.278003;000.080;000.00;1;10054889;70;1;1;1311;02;724;06;-317;3041;2;10;92")); - verifyPosition(decoder, text( "ST300ALT;205174410;14;712;20110101;00:00:07;00000;+20.593923;-100.336716;000.000;000.00;0;0;0;16.57;000000;81;000000;4.0;0;0.00;0000;0000;0;0")); @@ -21,7 +18,7 @@ public class SuntechProtocolDecoderTest extends ProtocolTest { verifyPosition(decoder, text( "ST910;Alert;123456;410;20141018;18:30:12;+37.478774;+126.889690;000.000;000.00;0;4.0;1;6002"), - position("2014-10-18 18:30:12.000", true, 37.47877, 126.88969)); + position("2014-10-18 18:30:12.000", false, 37.47877, 126.88969)); verifyPosition(decoder, text( "ST910;Alert;123456;410;20141018;18:30:12;+37.478774;+126.889690;000.000;000.00;0;4.0;1;6002;02;0;0310000100;450;01;-282;70;255;3;0")); @@ -60,6 +57,11 @@ public class SuntechProtocolDecoderTest extends ProtocolTest { verifyPosition(decoder, text( "ST910;Emergency;205283272;500;20150716;19:12:01;-23.659019;-046.695403;000.602;000.00;0;4.2;1;1;02;10820;2fdb090736;724;05;0;2311;255;0;100")); + decoder.setProtocolType(1); + + verifyPosition(decoder, text( + "ST910;Location;560266;500;20161207;21:33:11;af910be101;-25.504234;-049.278003;000.080;000.00;1;10054889;70;1;1;1311;02;724;06;-317;3041;2;10;92")); + } } -- cgit v1.2.3