diff options
-rw-r--r-- | src/org/traccar/model/Position.java | 2 | ||||
-rw-r--r-- | src/org/traccar/protocol/StarLinkProtocolDecoder.java | 155 | ||||
-rw-r--r-- | test/org/traccar/protocol/StarLinkProtocolDecoderTest.java | 14 |
3 files changed, 123 insertions, 48 deletions
diff --git a/src/org/traccar/model/Position.java b/src/org/traccar/model/Position.java index aeea83773..1a1db717f 100644 --- a/src/org/traccar/model/Position.java +++ b/src/org/traccar/model/Position.java @@ -79,6 +79,8 @@ public class Position extends Message { public static final String PREFIX_ADC = "adc"; public static final String PREFIX_IO = "io"; public static final String PREFIX_COUNT = "count"; + public static final String PREFIX_IN = "in"; + public static final String PREFIX_OUT = "out"; public static final String ALARM_GENERAL = "general"; public static final String ALARM_SOS = "sos"; diff --git a/src/org/traccar/protocol/StarLinkProtocolDecoder.java b/src/org/traccar/protocol/StarLinkProtocolDecoder.java index 46d8ee9cc..0cd162a95 100644 --- a/src/org/traccar/protocol/StarLinkProtocolDecoder.java +++ b/src/org/traccar/protocol/StarLinkProtocolDecoder.java @@ -17,8 +17,8 @@ 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.model.CellTower; @@ -26,12 +26,27 @@ import org.traccar.model.Network; import org.traccar.model.Position; import java.net.SocketAddress; +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.TimeZone; import java.util.regex.Pattern; public class StarLinkProtocolDecoder extends BaseProtocolDecoder { + private String[] dataTags; + private DateFormat dateFormat; + public StarLinkProtocolDecoder(StarLinkProtocol protocol) { super(protocol); + + String format = Context.getConfig().getString( + getProtocolName() + ".format", "#EDT#,#EID#,#PDT#,#LAT#,#LONG#,#SPD#,#HEAD#,#ODO#," + + "#IN1#,#IN2#,#IN3#,#IN4#,#OUT1#,#OUT2#,#OUT3#,#OUT4#,#LAC#,#CID#,#VIN#,#VBAT#,#DEST#,#IGN#,#ENG#"); + dataTags = format.split(","); + + dateFormat = new SimpleDateFormat( + Context.getConfig().getString(getProtocolName() + ".dateFormat", "yyMMddHHmmss")); + dateFormat.setTimeZone(TimeZone.getTimeZone("UTC")); } private static final Pattern PATTERN = new PatternBuilder() @@ -40,23 +55,20 @@ public class StarLinkProtocolDecoder extends BaseProtocolDecoder { .number("(x{6}|d{15}),") // id .number("(d+),") // type .number("(d+),") // index - .number("(dd)(dd)(dd)") // event date - .number("(dd)(dd)(dd),") // event time - .number("(d+),") // event - .number("(dd)(dd)(dd)") // fix date - .number("(dd)(dd)(dd),") // fix time - .number("([-+])(dd)(dd.d+),") // latitude - .number("([-+])(ddd)(dd.d+),") // longitude - .number("(d+.d+),") // speed - .number("(d+),") // course - .number("(d+),") // odometer - .number("(d+),") // lac - .number("(d+),") // cid - .number("(d+.d+),") // power - .number("(d+.d+)") // battery - .any() + .expression("(.+)") // data + .text("*") + .number("xx") // checksum .compile(); + public static final int MSG_EVENT_REPORT = 6; + + private double parseCoordinate(String value) { + int minutesIndex = value.indexOf('.') - 2; + double result = Double.parseDouble(value.substring(1, minutesIndex)); + result += Double.parseDouble(value.substring(minutesIndex)) / 60; + return value.charAt(0) == '+' ? result : -result; + } + @Override protected Object decode( Channel channel, SocketAddress remoteAddress, Object msg) throws Exception { @@ -71,38 +83,99 @@ public class StarLinkProtocolDecoder extends BaseProtocolDecoder { return null; } + int type = parser.nextInt(); + if (type != MSG_EVENT_REPORT) { + return null; + } + Position position = new Position(); position.setProtocol(getProtocolName()); position.setDeviceId(deviceSession.getDeviceId()); - position.set(Position.KEY_TYPE, parser.nextInt()); position.set(Position.KEY_INDEX, parser.nextInt()); - DateBuilder dateBuilder = new DateBuilder() - .setDate(parser.nextInt(), parser.nextInt(), parser.nextInt()) - .setTime(parser.nextInt(), parser.nextInt(), parser.nextInt()); - position.setDeviceTime(dateBuilder.getDate()); - - position.set(Position.KEY_EVENT, parser.nextInt()); - - dateBuilder = new DateBuilder() - .setDate(parser.nextInt(), parser.nextInt(), parser.nextInt()) - .setTime(parser.nextInt(), parser.nextInt(), parser.nextInt()); - position.setFixTime(dateBuilder.getDate()); - - position.setValid(true); - 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()); - - position.set(Position.KEY_ODOMETER, parser.nextInt()); - - position.setNetwork(new Network(CellTower.fromLacCid(parser.nextInt(), parser.nextInt()))); + String[] data = parser.next().split(","); + Integer lac = null, cid = null; + + for (int i = 0; i < Math.min(data.length, dataTags.length); i++) { + switch (dataTags[i]) { + case "#EDT#": + position.setDeviceTime(dateFormat.parse(data[i])); + break; + case "EID": + position.set(Position.KEY_EVENT, data[i]); + break; + case "#PDT#": + position.setFixTime(dateFormat.parse(data[i])); + break; + case "#LAT#": + position.setLatitude(parseCoordinate(data[i])); + break; + case "#LONG#": + position.setLongitude(parseCoordinate(data[i])); + break; + case "#SPD#": + position.setSpeed(Double.parseDouble(data[i])); + break; + case "#HEAD#": + position.setCourse(Integer.parseInt(data[i])); + break; + case "#ODO#": + position.set(Position.KEY_ODOMETER, Integer.parseInt(data[i])); + break; + case "#IN1#": + position.set(Position.PREFIX_IN + 1, Integer.parseInt(data[i])); + break; + case "#IN2#": + position.set(Position.PREFIX_IN + 2, Integer.parseInt(data[i])); + break; + case "#IN3#": + position.set(Position.PREFIX_IN + 3, Integer.parseInt(data[i])); + break; + case "#IN4#": + position.set(Position.PREFIX_IN + 4, Integer.parseInt(data[i])); + break; + case "#OUT1#": + position.set(Position.PREFIX_OUT + 1, Integer.parseInt(data[i])); + break; + case "#OUT2#": + position.set(Position.PREFIX_OUT + 2, Integer.parseInt(data[i])); + break; + case "#OUT3#": + position.set(Position.PREFIX_OUT + 3, Integer.parseInt(data[i])); + break; + case "#OUT4#": + position.set(Position.PREFIX_OUT + 4, Integer.parseInt(data[i])); + break; + case "#LAC#": + lac = Integer.parseInt(data[i]); + break; + case "#CID#": + cid = Integer.parseInt(data[i]); + break; + case "#VIN#": + position.set(Position.KEY_POWER, Double.parseDouble(data[i])); + break; + case "#VBAT#": + position.set(Position.KEY_BATTERY, Double.parseDouble(data[i])); + break; + case "#DEST#": + position.set("destination", data[i]); + break; + case "#IGN#": + position.set(Position.KEY_IGNITION, data[i].equals("1")); + break; + case "#ENG#": + position.set("engine", data[i].equals("1")); + break; + default: + break; + } + } - position.set(Position.KEY_POWER, parser.nextDouble()); - position.set(Position.KEY_BATTERY, parser.nextDouble()); + if (lac != null && cid != null) { + position.setNetwork(new Network(CellTower.fromLacCid(lac, cid))); + } return position; } diff --git a/test/org/traccar/protocol/StarLinkProtocolDecoderTest.java b/test/org/traccar/protocol/StarLinkProtocolDecoderTest.java index 33ee49812..8bd4427b3 100644 --- a/test/org/traccar/protocol/StarLinkProtocolDecoderTest.java +++ b/test/org/traccar/protocol/StarLinkProtocolDecoderTest.java @@ -10,17 +10,17 @@ public class StarLinkProtocolDecoderTest extends ProtocolTest { StarLinkProtocolDecoder decoder = new StarLinkProtocolDecoder(new StarLinkProtocol()); - verifyNothing(decoder, text( - "$SLU005F20,06,22743,170116091944,01,170116091944,+3206.0991,+03452.0605,003.6,008,064675,1,1,0,0,0,0,0,0,10424,2521,14.156,01.163,,1,1,1,4*BE")); + verifyPosition(decoder, text( + "$SLU006968,06,375153,170117051824,01,170117051823,+3203.2073,+03448.1360,000.0,300,085725,1,1,0,0,0,0,0,0,10422,36201,12.655,04.085,,0,0,0,99*45")); - verifyNothing(decoder, text( - "$SLU005F20,06,22718,170116091422,01,170116091422,+3205.1777,+03450.7595,046.8,359,064671,1,1,0,0,0,0,0,0,10424,64072,14.148,01.161,,1,1,1,4*03")); + verifyPosition(decoder, text( + "$SLU006968,06,375155,170117052615,24,170117052613,+3203.2079,+03448.1369,000.0,300,085725,1,1,0,0,0,0,0,0,10422,36201,14.290,04.083,,1,1*5B")); - verifyNothing(decoder, text( - "$SLU005F20,06,22695,170116090730,24,170116090730,+3203.6062,+03449.6945,013.9,181,064666,1,1,0,0,0,0,0,0,10422,30631,14.089,01.163,,1,1*43")); + verifyPosition(decoder, text( + "$SLU006968,06,375156,170117052616,34,170117052614,+3203.2079,+03448.1369,000.0,300,085725,1,1,0,0,0,0,0,0,10422,36201,14.277,04.084,1,1,1,1*F3")); verifyPosition(decoder, text( - "$SLU0004D2,06,32,071106135931,01,071106135930,+3159.4376,+03445.3298,021.3,087,000554,31071,11704,13.45,3.87*3E")); + "$SLU006968,06,375154,170117052613,04,170117052612,+3203.2079,+03448.1369,000.0,300,085725,1,1,0,0,0,0,0,0,10422,36201,14.287,04.084,,1,0*5B")); } |