-
Notifications
You must be signed in to change notification settings - Fork 0
/
Parser.java
216 lines (190 loc) · 7.62 KB
/
Parser.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
/* AUTO-GENERATED FILE. DO NOT MODIFY.
*
* This class was automatically generated by the
* java mavlink generator tool. It should not be modified by hand.
*/
package com.MAVLink;
import com.MAVLink.MAVLinkPacket;
import com.MAVLink.Messages.MAVLinkStats;
/**
* MAVLink parser that parses @{link MAVLinkPacket}s from a byte stream one byte
* at a time.
*
* After creating an instance of this class, simply use the @{link #mavlink_parse_char}
* method to parse a byte stream.
*/
public class Parser {
static final String TAG = Parser.class.getSimpleName();
static final boolean V = false;
static void logv(String tag, String msg) {
if(V) System.out.println(String.format("%s: %s", tag, msg));
}
/**
* States from the parsing state machine
*/
enum MAV_states {
MAVLINK_PARSE_STATE_UNINIT,
MAVLINK_PARSE_STATE_IDLE,
MAVLINK_PARSE_STATE_GOT_STX,
MAVLINK_PARSE_STATE_GOT_LENGTH,
MAVLINK_PARSE_STATE_GOT_INCOMPAT_FLAGS, // MAVLink 2
MAVLINK_PARSE_STATE_GOT_COMPAT_FLAGS, // MAVLink 2
MAVLINK_PARSE_STATE_GOT_SEQ,
MAVLINK_PARSE_STATE_GOT_SYSID,
MAVLINK_PARSE_STATE_GOT_COMPID,
MAVLINK_PARSE_STATE_GOT_MSGID1,
MAVLINK_PARSE_STATE_GOT_MSGID2, // MAVLink 2
MAVLINK_PARSE_STATE_GOT_MSGID3, // MAVLink 2
MAVLINK_PARSE_STATE_GOT_CRC1,
MAVLINK_PARSE_STATE_GOT_CRC2, // MAVLink 2
MAVLINK_PARSE_STATE_GOT_PAYLOAD,
MAVLINK_PARSE_STATE_GOT_SIGNATURE, // MAVLink 2
}
private MAV_states state = MAV_states.MAVLINK_PARSE_STATE_UNINIT;
public MAVLinkStats stats;
private MAVLinkPacket m;
private boolean isMavlink2;
public Parser() {
this(false);
}
public Parser(boolean ignoreRadioPacketStats) {
stats = new MAVLinkStats(ignoreRadioPacketStats);
isMavlink2 = false;
}
/**
* This is a convenience function which handles the complete MAVLink
* parsing. the function will parse one byte at a time and return the
* complete packet once it could be successfully decoded. Checksum and other
* failures will be silently ignored.
*
* @param c The char to parse
* @return the complete @{link MAVLinkPacket} if successfully decoded, else null
*/
public MAVLinkPacket mavlink_parse_char(int c) {
// force to 8 bits
c &= 0xFF;
switch (state) {
case MAVLINK_PARSE_STATE_UNINIT:
case MAVLINK_PARSE_STATE_IDLE:
// MAVLink 1 and 2
if (c == MAVLinkPacket.MAVLINK_STX_MAVLINK2) {
state = MAV_states.MAVLINK_PARSE_STATE_GOT_STX;
if (!isMavlink2) {
isMavlink2 = true;
logv(TAG, "Turning mavlink2 ON");
}
} else if (c == MAVLinkPacket.MAVLINK_STX_MAVLINK1) {
state = MAV_states.MAVLINK_PARSE_STATE_GOT_STX;
if (isMavlink2) {
isMavlink2 = false;
logv(TAG, "Turning mavlink2 OFF");
}
}
break;
case MAVLINK_PARSE_STATE_GOT_STX:
// MAVLink 1 and 2
m = new MAVLinkPacket(c, isMavlink2);
if (isMavlink2) {
state = MAV_states.MAVLINK_PARSE_STATE_GOT_LENGTH;
} else {
state = MAV_states.MAVLINK_PARSE_STATE_GOT_COMPAT_FLAGS;
}
break;
case MAVLINK_PARSE_STATE_GOT_LENGTH:
// MAVLink 1 and 2
m.incompatFlags = c;
if (c != 0 && c != 1) {
// message includes an incompatible feature flag
state = MAV_states.MAVLINK_PARSE_STATE_IDLE;
break;
}
state = MAV_states.MAVLINK_PARSE_STATE_GOT_INCOMPAT_FLAGS;
break;
case MAVLINK_PARSE_STATE_GOT_INCOMPAT_FLAGS:
// MAVLink 2 only
m.compatFlags = c;
state = MAV_states.MAVLINK_PARSE_STATE_GOT_COMPAT_FLAGS;
break;
case MAVLINK_PARSE_STATE_GOT_COMPAT_FLAGS:
m.seq = c;
state = MAV_states.MAVLINK_PARSE_STATE_GOT_SEQ;
break;
case MAVLINK_PARSE_STATE_GOT_SEQ:
// back to MAVLink 1 and 2
m.sysid = c;
state = MAV_states.MAVLINK_PARSE_STATE_GOT_SYSID;
break;
case MAVLINK_PARSE_STATE_GOT_SYSID:
// MAVLink 1 and 2
m.compid = c;
state = MAV_states.MAVLINK_PARSE_STATE_GOT_COMPID;
break;
case MAVLINK_PARSE_STATE_GOT_COMPID:
// MAVLink 1 and 2
m.msgid = c;
if (isMavlink2) {
state = MAV_states.MAVLINK_PARSE_STATE_GOT_MSGID1;
} else if (m.len > 0) {
state = MAV_states.MAVLINK_PARSE_STATE_GOT_MSGID3;
} else {
state = MAV_states.MAVLINK_PARSE_STATE_GOT_PAYLOAD;
}
break;
case MAVLINK_PARSE_STATE_GOT_MSGID1:
// MAVLink 2 only
m.msgid |= c << 8;
state = MAV_states.MAVLINK_PARSE_STATE_GOT_MSGID2;
break;
case MAVLINK_PARSE_STATE_GOT_MSGID2:
// MAVLink 2 only
m.msgid |= c << 16;
if (m.len > 0) {
state = MAV_states.MAVLINK_PARSE_STATE_GOT_MSGID3;
} else {
state = MAV_states.MAVLINK_PARSE_STATE_GOT_PAYLOAD;
}
break;
case MAVLINK_PARSE_STATE_GOT_MSGID3:
// back to MAVLink 1 and 2
m.payload.add((byte) c);
if (m.payloadIsFilled()) {
state = MAV_states.MAVLINK_PARSE_STATE_GOT_PAYLOAD;
}
break;
case MAVLINK_PARSE_STATE_GOT_PAYLOAD:
boolean crcGen = m.generateCRC(m.payload.size());
// Check first checksum byte and verify the CRC was successfully generated (msg extra exists)
if (c != m.crc.getLSB() || !crcGen) {
state = MAV_states.MAVLINK_PARSE_STATE_IDLE;
stats.crcError();
} else {
state = MAV_states.MAVLINK_PARSE_STATE_GOT_CRC1;
}
break;
case MAVLINK_PARSE_STATE_GOT_CRC1:
// Check second checksum byte
if (c != m.crc.getMSB()) {
state = MAV_states.MAVLINK_PARSE_STATE_IDLE;
stats.crcError();
} else { // crc is good
stats.newPacket(m);
if (!isMavlink2 || (m.incompatFlags != 0x01)) {
// If no signature, then return the message.
state = MAV_states.MAVLINK_PARSE_STATE_IDLE;
return m;
} else {
// TODO: MAVLink 2 - signed
state = MAV_states.MAVLINK_PARSE_STATE_IDLE;
stats.crcError();
}
}
break;
case MAVLINK_PARSE_STATE_GOT_CRC2:
// TODO: implement signature parsing and validation
state = MAV_states.MAVLINK_PARSE_STATE_IDLE;
stats.crcError();
break;
} // switch
return null;
}
}