1 package au.gov.amsa.util.nmea;
2
3 import java.util.LinkedHashMap;
4 import java.util.List;
5 import java.util.Map.Entry;
6 import java.util.regex.Matcher;
7 import java.util.regex.Pattern;
8
9
10
11
12
13
14
15 public class NmeaMessage {
16
17 private final LinkedHashMap<String, String> tags;
18 private final List<String> items;
19 private final Talker talker;
20 private final SentenceInfo sentenceInfo;
21 private final String checksum;
22
23
24
25
26
27
28
29
30
31
32
33 public NmeaMessage(LinkedHashMap<String, String> tags, List<String> items, String checksum) {
34 this.tags = tags;
35 this.items = items;
36 if (!items.isEmpty() && items.get(0).length() >= 3)
37 this.talker = NmeaUtil.getTalker((items.get(0).substring(1, 3)));
38 else
39 talker = Talker.UNKNOWN;
40 this.sentenceInfo = getSentenceInfo(tags, items);
41 this.checksum = checksum;
42 }
43
44
45
46
47
48
49 public String getSource() {
50 return tags.get("s");
51 }
52
53
54
55
56
57
58
59 public Long getUnixTimeMillis() {
60 String time = tags.get("c");
61 if (time == null)
62 return null;
63 else
64 try {
65 return Long.parseLong(time) * 1000;
66 } catch (NumberFormatException e) {
67 return null;
68 }
69 }
70
71
72
73
74
75
76 public String getDestination() {
77 return tags.get("d");
78 }
79
80
81
82
83
84
85 public String getSentenceGroupingFromTagBlock() {
86 return tags.get("g");
87 }
88
89
90
91
92
93
94 public Integer getLineCount() {
95 String count = tags.get("n");
96 if (count == null)
97 return null;
98 else
99 return Integer.parseInt(count);
100 }
101
102
103
104
105
106
107
108 public Long getRelativeTimeMillis() {
109 String time = tags.get("r");
110 if (time == null)
111 return null;
112 else
113 return Long.parseLong(time) * 1000;
114 }
115
116
117
118
119
120
121 public String getText() {
122 return tags.get("t");
123 }
124
125
126
127
128
129
130 public List<String> getItems() {
131 return items;
132 }
133
134 public LinkedHashMap<String, String> getTags() {
135 return tags;
136 }
137
138 public Talker getTalker() {
139 return talker;
140 }
141
142 public String toLine() {
143 return NmeaUtil.createNmeaLine(tags, items);
144 }
145
146 public Integer getSentenceNumber() {
147 if (sentenceInfo != null)
148 return sentenceInfo.number;
149 else
150 return null;
151 }
152
153 public Integer getSentenceCount() {
154 if (sentenceInfo != null)
155 return sentenceInfo.count;
156 else
157 return null;
158 }
159
160 public String getSentenceGroupId() {
161 if (sentenceInfo != null)
162 return sentenceInfo.id;
163 else
164 return null;
165 }
166
167
168
169
170
171
172 public String calculateChecksum() {
173 return NmeaUtil.getChecksum(NmeaUtil.createNmeaLine(tags, items));
174 }
175
176 public String getChecksum() {
177 return checksum;
178 }
179
180 private static final Pattern sentenceTagPattern = Pattern
181 .compile("([1-9][0-9]*)G([1-9][0-9]*)");
182
183 private static SentenceInfo getSentenceInfo(LinkedHashMap<String, String> tags,
184 List<String> items) {
185 try {
186 String g = tags.get("g");
187 if (g != null) {
188
189 String[] parts = g.split("-");
190 if (parts.length < 3)
191 throw new NmeaMessageParseException("not enough parts available in g tag");
192 int number = Integer.parseInt(parts[0]);
193 int count = Integer.parseInt(parts[1]);
194 String id = parts[2];
195 return new SentenceInfo(number, count, id);
196
197 } else {
198
199
200 for (Entry<String, String> entry : tags.entrySet()) {
201 Matcher matcher = sentenceTagPattern.matcher(entry.getKey());
202 if (matcher.matches()) {
203 int number = Integer.parseInt(matcher.group(1));
204 int count = Integer.parseInt(matcher.group(2));
205 String id = entry.getValue();
206
207 return new SentenceInfo(number, count, id);
208 }
209 }
210
211 if (items.size() > 2 && isEncapsulationSentence(items)) {
212 int number = Integer.parseInt(items.get(2));
213 int count = Integer.parseInt(items.get(1));
214 String id = items.get(3);
215 return new SentenceInfo(number, count, id);
216 } else
217 return null;
218 }
219 } catch (NumberFormatException e) {
220 throw new NmeaMessageParseException(e.getMessage(), e);
221 }
222 }
223
224 private static boolean isEncapsulationSentence(List<String> items) {
225 return items.size() > 0 && items.get(0).startsWith("!");
226 }
227
228 private static class SentenceInfo {
229 int number;
230 int count;
231 String id;
232
233 public SentenceInfo(int number, int count, String id) {
234 super();
235 this.number = number;
236 this.count = count;
237 this.id = id;
238 }
239 }
240
241 public boolean isSingleSentence() {
242 return getSentenceCount() == null || getSentenceCount() == 1;
243 }
244
245 public Long getArrivalTimeMillis() {
246 String time = tags.get("a");
247 if (time == null)
248 return null;
249 else
250 try {
251 return Long.parseLong(time);
252 } catch (NumberFormatException e) {
253 return null;
254 }
255 }
256
257 }