@@ -128,6 +128,33 @@ void setup()
128128#define IMIN (x,y ) ((x)<(y)?(x):(y))
129129#define ODID_COPY_STR (to, from ) strncpy(to, (const char *)from, IMIN(sizeof (to), sizeof (from)))
130130
131+ /*
132+ check if a UASID is valid as a serial number
133+ */
134+ static bool valid_UASID_serialnum (const char *uasid)
135+ {
136+ const auto uasid_len = strnlen (uasid, sizeof (UAS_data.BasicID [0 ].UASID ));
137+ // 5th char is length field
138+ if (uasid_len < 5 || !isxdigit (uasid[4 ]) != 0 ) {
139+ return false ;
140+ }
141+ char str[2 ] {};
142+ str[0 ] = uasid[4 ];
143+ const uint8_t sn_length = strtol (str, NULL , 16 ) + 5 ;
144+ if (sn_length != uasid_len && sn_length > 5 ) {
145+ return false ;
146+ }
147+ // check also for invalid chars
148+ for (unsigned i = 0 ; i < uasid_len; i++) {
149+ const auto c = uasid[i];
150+ if (islower (c) || c == ' I' || c == ' O' ) {
151+ // only capital letters and digits are allowed. Char I and O are not allowed.
152+ return false ;
153+ }
154+ }
155+ return true ;
156+ }
157+
131158/*
132159 check parsing of UAS_data, this checks ranges of values to ensure we
133160 will produce a valid pack
@@ -136,6 +163,7 @@ void setup()
136163static const char *check_parse (void )
137164{
138165 String ret = " " ;
166+ const uint32_t required = g.get_required_features ();
139167
140168 {
141169 ODID_Location_encoded encoded {};
@@ -175,14 +203,83 @@ static const char *check_parse(void)
175203 ret += " OP_ID " ;
176204 }
177205 }
206+
207+ bool serial_number_configured = false ;
208+ bool session_ID_configured = false ;
209+ bool CAA_registration_ID_configured = false ; // only mandatory in Japan
210+
211+ // BasicID checks
212+ if (UAS_data.BasicIDValid [0 ] == 1 ) {
213+ if (UAS_data.BasicID [0 ].IDType == ODID_IDTYPE_SERIAL_NUMBER) {
214+ serial_number_configured = true ;
215+ } else if (UAS_data.BasicID [0 ].IDType == ODID_IDTYPE_CAA_REGISTRATION_ID) {
216+ CAA_registration_ID_configured = true ;
217+ } else if (UAS_data.BasicID [0 ].IDType == ODID_IDTYPE_SPECIFIC_SESSION_ID) {
218+ session_ID_configured = true ;
219+ }
220+ }
221+
222+ if (UAS_data.BasicIDValid [1 ] == 1 ) {
223+ if (UAS_data.BasicID [1 ].IDType == ODID_IDTYPE_SERIAL_NUMBER) {
224+ if (!serial_number_configured) { // only one serial number is allowed
225+ serial_number_configured = true ;
226+ } else {
227+ ret += " DBL_SER_NUM " ;
228+ }
229+ } else if (UAS_data.BasicID [1 ].IDType == ODID_IDTYPE_CAA_REGISTRATION_ID) {
230+ if (!CAA_registration_ID_configured) { // only one CAA registration ID is allowed
231+ CAA_registration_ID_configured = true ;
232+ } else {
233+ ret += " DBL_CAA_ID " ;
234+ }
235+ } else if (UAS_data.BasicID [1 ].IDType == ODID_IDTYPE_SPECIFIC_SESSION_ID) {
236+ if (!session_ID_configured) { // only one session ID is allowed
237+ session_ID_configured = true ;
238+ } else {
239+ ret += " DBL_SESS_ID " ;
240+ }
241+ }
242+ }
243+
244+ if (!serial_number_configured && (required & REG_REQUIRE_SERIAL_NUM)) {
245+ ret += " SER_NUM " ;
246+ }
247+
248+ if (!serial_number_configured && !session_ID_configured && (required & REG_REQUIRE_SERIAL_OR_SESSION)) {
249+ ret += " SER_SESS " ;
250+ }
251+
252+ if (!CAA_registration_ID_configured && (required & REG_REQUIRE_REG_ID)) {
253+ ret += " REG_ID " ;
254+ }
255+
256+ if (strlen (UAS_data.OperatorID .OperatorId ) <= 0 && (required & REG_REQUIRE_OPERATOR_ID)) {
257+ // basic check if the operator field has data. For the EU legislation an additional check could be implemented.
258+ ret += " OP_ID " ;
259+ }
260+
261+ if (UAS_data.BasicIDValid [0 ] == 1 &&
262+ serial_number_configured &&
263+ UAS_data.BasicID [0 ].IDType == ODID_IDTYPE_SERIAL_NUMBER &&
264+ !valid_UASID_serialnum (UAS_data.BasicID [0 ].UASID )) {
265+ ret += " SER_NUM_VAL " ;
266+ }
267+
268+ if (UAS_data.BasicIDValid [1 ] == 1 &&
269+ UAS_data.BasicID [1 ].IDType == ODID_IDTYPE_SERIAL_NUMBER &&
270+ !valid_UASID_serialnum (UAS_data.BasicID [1 ].UASID )) {
271+ ret += " SER_NUM_VAL " ;
272+ }
273+
178274 if (ret.length () > 0 ) {
179275 // if all errors would occur in this function, it will fit in
180276 // 50 chars that is also the max for the arm status message
181277 static char return_string[50 ];
182278 memset (return_string, 0 , sizeof (return_string));
183- snprintf (return_string, sizeof (return_string- 1 ) , " bad %s data" , ret.c_str ());
279+ snprintf (return_string, sizeof (return_string)- 1 , " bad %s data" , ret.c_str ());
184280 return return_string;
185281 }
282+
186283 return nullptr ;
187284}
188285
0 commit comments