00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00033 #include "helpers2.h"
00034 #include "fap.h"
00035 #include "regs.h"
00036 #ifdef HAVE_CONFIG_H
00037 #include <config.h>
00038 #endif
00039
00040 #include <stdio.h>
00041 #include <stdlib.h>
00042 #include <string.h>
00043 #include <regex.h>
00044 #include <ctype.h>
00045 #include <math.h>
00046
00047
00048
00049 void fapint_clear_llist(fapint_llist_item_t* list)
00050 {
00051 fapint_llist_item_t* current_elem = list, *tmp_elem;
00052
00053 while ( current_elem != NULL )
00054 {
00055 if ( current_elem->text ) free(current_elem->text);
00056 tmp_elem = current_elem->next;
00057 free(current_elem);
00058 current_elem = tmp_elem;
00059 }
00060 }
00061
00062
00063
00064 double fapint_get_pos_resolution(int const minute_digit_count)
00065 {
00066 double retval = KNOT_TO_KMH;
00067 if ( minute_digit_count <= -2 )
00068 {
00069 retval *= 600;
00070 }
00071 else
00072 {
00073 retval *= 1000;
00074 }
00075 return retval * pow(10, -1*minute_digit_count);
00076 }
00077
00078
00079
00080 int fapint_parse_symbol_from_dst_callsign(fap_packet_t* packet)
00081 {
00082 int len;
00083 char leftover_str[3];
00084 char type;
00085
00086 char numberid_str[3];
00087 int numberid;
00088
00089 char dst_type[2];
00090 char overlay;
00091 char code[2];
00092 char tmp_2b[2];
00093
00094 unsigned int const matchcount = 3;
00095 regmatch_t matches[matchcount];
00096
00097
00098
00099 if ( !packet || !packet->dst_callsign )
00100 {
00101 return 0;
00102 }
00103
00104
00105 if ( regexec(&fapint_regex_nmea_dst, packet->dst_callsign, matchcount, (regmatch_t*)&matches, 0) == 0 )
00106 {
00107
00108 len = matches[2].rm_eo - matches[2].rm_so;
00109 memset(leftover_str, 0, 3);
00110 memcpy(leftover_str, packet->dst_callsign+matches[2].rm_so, len);
00111
00112 type = leftover_str[0];
00113
00114 if ( len == 3 )
00115 {
00116 if ( type == 'C' || type == 'E' )
00117 {
00118
00119 memset(numberid_str, 0, 3);
00120 numberid_str[0] = leftover_str[1];
00121 numberid_str[1] = leftover_str[2];
00122 numberid = atoi(numberid_str);
00123
00124
00125 if ( numberid > 0 && numberid < 95 )
00126 {
00127 packet->symbol_code = numberid + 32;
00128 if ( type == 'C' )
00129 {
00130 packet->symbol_table = '/';
00131 }
00132 else
00133 {
00134 packet->symbol_table = '\\';
00135 }
00136 return 1;
00137 }
00138 else
00139 {
00140
00141 return 0;
00142 }
00143 }
00144 else
00145 {
00146
00147 dst_type[0] = leftover_str[0];
00148 dst_type[1] = leftover_str[1];
00149 overlay = leftover_str[2];
00150 if ( (type == 'O' || type == 'A' || type == 'N' ||
00151 type == 'D' || type == 'S' || type == 'Q') &&
00152 isalnum(overlay) )
00153 {
00154 if ( fapint_symbol_from_dst_type(dst_type, code) )
00155 {
00156 packet->symbol_table = overlay;
00157 packet->symbol_code = code[1];
00158 return 1;
00159 }
00160 else
00161 {
00162
00163 return 0;
00164 }
00165 }
00166 else
00167 {
00168
00169 return 0;
00170 }
00171 }
00172 }
00173 else
00174 {
00175
00176 tmp_2b[0] = leftover_str[0];
00177 tmp_2b[1] = leftover_str[1];
00178 if ( fapint_symbol_from_dst_type(tmp_2b, code) )
00179 {
00180 packet->symbol_table = code[0];
00181 packet->symbol_code = code[1];
00182 return 1;
00183 }
00184 else
00185 {
00186
00187 return 0;
00188 }
00189 }
00190 }
00191 else
00192 {
00193 return 0;
00194 }
00195
00196
00197 return 0;
00198 }
00199
00200
00201
00202 int fapint_symbol_from_dst_type(char input[2], char* output)
00203 {
00204 switch ( input[0] )
00205 {
00206 case 'B':
00207 case 'O':
00208 if ( input[0] == 'B' )
00209 {
00210 output[0] = '/';
00211 }
00212 else
00213 {
00214 output[0] = '\\';
00215 }
00216 switch ( input[1] )
00217 {
00218 case 'B':
00219 output[1] = '!';
00220 return 1;
00221 case 'C':
00222 output[1] = '"';
00223 return 1;
00224 case 'D':
00225 output[1] = '#';
00226 return 1;
00227 case 'E':
00228 output[1] = '$';
00229 return 1;
00230 case 'F':
00231 output[1] = '%';
00232 return 1;
00233 case 'G':
00234 output[1] = '&';
00235 return 1;
00236 case 'H':
00237 output[1] = '\'';
00238 return 1;
00239 case 'I':
00240 output[1] = '(';
00241 return 1;
00242 case 'J':
00243 output[1] = ')';
00244 return 1;
00245 case 'K':
00246 output[1] = '*';
00247 return 1;
00248 case 'L':
00249 output[1] = '+';
00250 return 1;
00251 case 'M':
00252 output[1] = ',';
00253 return 1;
00254 case 'N':
00255 output[1] = '-';
00256 return 1;
00257 case 'O':
00258 output[1] = '.';
00259 return 1;
00260 case 'P':
00261 output[1] = '/';
00262 return 1;
00263 }
00264 return 0;
00265 case 'P':
00266 case 'A':
00267 if ( input[0] == 'P' )
00268 {
00269 output[0] = '/';
00270 }
00271 else
00272 {
00273 output[0] = '\\';
00274 }
00275 if ( isdigit(input[1]) || isupper(input[1]) )
00276 {
00277 output[1] = input[1];
00278 return 1;
00279 }
00280 return 0;
00281 case 'M':
00282 case 'N':
00283 if ( input[0] == 'M' )
00284 {
00285 output[0] = '/';
00286 }
00287 else
00288 {
00289 output[0] = '\\';
00290 }
00291 switch ( input[1] )
00292 {
00293 case 'R':
00294 output[1] = ':';
00295 return 1;
00296 case 'S':
00297 output[1] = ';';
00298 return 1;
00299 case 'T':
00300 output[1] = '<';
00301 return 1;
00302 case 'U':
00303 output[1] = '=';
00304 return 1;
00305 case 'V':
00306 output[1] = '>';
00307 return 1;
00308 case 'W':
00309 output[1] = '?';
00310 return 1;
00311 case 'X':
00312 output[1] = '@';
00313 return 1;
00314 }
00315 return 0;
00316 case 'H':
00317 case 'D':
00318 if ( input[0] == 'H' )
00319 {
00320 output[0] = '/';
00321 }
00322 else
00323 {
00324 output[0] = '\\';
00325 }
00326 switch ( input[1] )
00327 {
00328 case 'S':
00329 output[1] = '[';
00330 return 1;
00331 case 'T':
00332 output[1] = '\\';
00333 return 1;
00334 case 'U':
00335 output[1] = ']';
00336 return 1;
00337 case 'V':
00338 output[1] = '^';
00339 return 1;
00340 case 'W':
00341 output[1] = '_';
00342 return 1;
00343 case 'X':
00344 output[1] = '`';
00345 return 1;
00346 }
00347 return 0;
00348 case 'L':
00349 case 'S':
00350 if ( input[0] == 'L' )
00351 {
00352 output[0] = '/';
00353 }
00354 else
00355 {
00356 output[0] = '\\';
00357 }
00358 if ( isupper(input[1]) )
00359 {
00360 output[1] = tolower(input[1]);
00361 return 1;
00362 }
00363 return 0;
00364 case 'J':
00365 case 'Q':
00366 if ( input[0] == 'J' )
00367 {
00368 output[0] = '/';
00369 }
00370 else
00371 {
00372 output[0] = '\\';
00373 }
00374 switch ( input[1] )
00375 {
00376 case '1':
00377 output[1] = '{';
00378 return 1;
00379 case '2':
00380 output[1] = '|';
00381 return 1;
00382 case '3':
00383 output[1] = '}';
00384 return 1;
00385 case '4':
00386 output[1] = '~';
00387 return 1;
00388 }
00389 return 0;
00390 }
00391
00392 return 0;
00393 }
00394
00395
00396
00397 int fapint_is_number(char const* input)
00398 {
00399 int i;
00400
00401 if ( !input ) return 0;
00402
00403 for ( i = 0; i < strlen(input); ++i )
00404 {
00405 if ( !isdigit(input[i]) || ( i==0 && (input[i]=='-' || input[i]=='+') ) ) return 0;
00406 }
00407
00408 return 1;
00409 }
00410
00411
00412
00413 int fapint_check_date(unsigned int year, unsigned int month, unsigned int day)
00414 {
00415 return year < 10000 && month <= 12 && day <= 31;
00416 }
00417
00418
00419
00420 int fapint_get_nmea_latlon(fap_packet_t* packet, char* field1, char* field2)
00421 {
00422 double value;
00423 char direction;
00424
00425 char* tmp_str;
00426 unsigned int tmp_us;
00427 int len;
00428
00429 unsigned int matchcount = 4;
00430 regmatch_t matches[matchcount];
00431
00432
00433
00434 if ( !packet || !field1 || !field2 )
00435 {
00436 return 0;
00437 }
00438
00439
00440 if ( regexec(&fapint_regex_nmea_flag, field2, matchcount, (regmatch_t*)&matches, 0) == 0 )
00441 {
00442 direction = field2[matches[1].rm_so];
00443 }
00444 else
00445 {
00446 packet->error_code = malloc(sizeof(fap_error_code_t));
00447 if ( packet->error_code ) *packet->error_code = fapNMEA_INV_SIGN;
00448 return 0;
00449 }
00450
00451
00452
00453
00454 if ( regexec(&fapint_regex_nmea_coord, field1, matchcount, (regmatch_t*)&matches, 0) == 0 )
00455 {
00456 len = matches[1].rm_eo - matches[1].rm_so;
00457 tmp_str = malloc(len+1);
00458 if ( !tmp_str ) return 0;
00459 memcpy(tmp_str, field1+matches[1].rm_so, len);
00460 tmp_str[len] = 0;
00461 tmp_us = atoi(tmp_str);
00462 free(tmp_str);
00463
00464 len = matches[2].rm_eo - matches[2].rm_so;
00465 tmp_str = malloc(len+1);
00466 if ( !tmp_str ) return 0;
00467 memcpy(tmp_str, field1+matches[2].rm_so, len);
00468 tmp_str[len] = 0;
00469 value = atof(tmp_str);
00470 free(tmp_str);
00471
00472 len = matches[3].rm_eo - matches[3].rm_so;
00473
00474 value = tmp_us + value/60;
00475 if ( !packet->pos_resolution )
00476 {
00477 packet->pos_resolution = malloc(sizeof(double));
00478 if ( !packet->pos_resolution ) return 0;
00479 *packet->pos_resolution = fapint_get_pos_resolution(len);
00480 }
00481 }
00482 else
00483 {
00484 packet->error_code = malloc(sizeof(fap_error_code_t));
00485 if ( packet->error_code ) *packet->error_code = fapNMEA_INV_CVAL;
00486 return 0;
00487 }
00488
00489
00490 switch ( toupper(direction) )
00491 {
00492 case 'E':
00493 case 'W':
00494 if ( value > 179.999999 )
00495 {
00496 packet->error_code = malloc(sizeof(fap_error_code_t));
00497 if ( packet->error_code ) *packet->error_code = fapNMEA_LARGE_EW;
00498 return 0;
00499 }
00500 if ( toupper(direction) == 'W' )
00501 {
00502 value *= -1;
00503 }
00504 packet->longitude = malloc(sizeof(double));
00505 if ( !packet->longitude ) return 0;
00506 *packet->longitude = value;
00507 return 1;
00508 case 'N':
00509 case 'S':
00510 if ( value > 89.999999 )
00511 {
00512 packet->error_code = malloc(sizeof(fap_error_code_t));
00513 if ( packet->error_code ) *packet->error_code = fapNMEA_LARGE_NS;
00514 return 0;
00515 }
00516 if ( toupper(direction) == 'S' )
00517 {
00518 value *= -1;
00519 }
00520 packet->latitude = malloc(sizeof(double));
00521 if ( !packet->latitude ) return 0;
00522 *packet->latitude = value;
00523 return 1;
00524 }
00525
00526 return 0;
00527 }
00528
00529
00530
00531 short fapint_valid_com_telem_char(char c)
00532 {
00533 if ( c >= '!' && c <= '{' )
00534 {
00535 return 1;
00536 }
00537 return 0;
00538 }
00539
00540
00541 void fapint_parse_comment_telemetry(fap_packet_t* packet, char** rest, unsigned int* rest_len)
00542 {
00543 int len = 0, i = 0, j = 0, tmp;
00544 char* tmp_str;
00545 unsigned int tmp_us;
00546 char buf[10];
00547
00548
00549 for ( i = 0; i < *rest_len; ++i )
00550 {
00551 if ( (*rest)[i] == '|' )
00552 {
00553
00554 for ( j = i+1; j < *rest_len; ++j )
00555 {
00556 if ( (*rest)[j] == '|' )
00557 {
00558 break;
00559 }
00560 }
00561 break;
00562 }
00563 }
00564
00565
00566 len = j - i + 1;
00567 if ( i < *rest_len && j < *rest_len && len > 1 && len % 2 == 0)
00568 {
00569
00570 if ( len >= 4 )
00571 {
00572 if ( fapint_valid_com_telem_char((*rest)[i+1]) &&
00573 fapint_valid_com_telem_char((*rest)[i+2]) )
00574 {
00575
00576 packet->telemetry = malloc(sizeof(fap_telemetry_t));
00577 if ( !packet->telemetry ) return;
00578 fapint_init_telemetry_report(packet->telemetry);
00579
00580 packet->telemetry->seq = ((*rest)[i+1] - 33) * 91 + (*rest)[i+2] - 33;
00581 }
00582 else
00583 {
00584 return;
00585 }
00586 }
00587
00588
00589 if ( len >= 6 )
00590 {
00591 if ( fapint_valid_com_telem_char((*rest)[i+3]) &&
00592 fapint_valid_com_telem_char((*rest)[i+4]) )
00593 {
00594 packet->telemetry->val1 = ((*rest)[i+3] - 33) * 91 + (*rest)[i+4] - 33;
00595 }
00596 else
00597 {
00598 free(packet->telemetry);
00599 packet->telemetry = NULL;
00600 return;
00601 }
00602 }
00603
00604
00605 if ( len >= 8 )
00606 {
00607 if ( fapint_valid_com_telem_char((*rest)[i+5]) &&
00608 fapint_valid_com_telem_char((*rest)[i+6]) )
00609 {
00610 packet->telemetry->val2 = ((*rest)[i+5] - 33) * 91 + (*rest)[i+6] - 33;
00611 }
00612 else
00613 {
00614 free(packet->telemetry);
00615 packet->telemetry = NULL;
00616 return;
00617 }
00618 }
00619
00620
00621 if ( len >= 10 )
00622 {
00623 if ( fapint_valid_com_telem_char((*rest)[i+7]) &&
00624 fapint_valid_com_telem_char((*rest)[i+8]) )
00625 {
00626 packet->telemetry->val3 = ((*rest)[i+7] - 33) * 91 + (*rest)[i+8] - 33;
00627 }
00628 else
00629 {
00630 free(packet->telemetry);
00631 packet->telemetry = NULL;
00632 return;
00633 }
00634 }
00635
00636
00637 if ( len >= 12 )
00638 {
00639 if ( fapint_valid_com_telem_char((*rest)[i+9]) &&
00640 fapint_valid_com_telem_char((*rest)[i+10]) )
00641 {
00642 packet->telemetry->val4 = ((*rest)[i+9] - 33) * 91 + (*rest)[i+10] - 33;
00643 }
00644 else
00645 {
00646 free(packet->telemetry);
00647 packet->telemetry = NULL;
00648 return;
00649 }
00650 }
00651
00652
00653 if ( len >= 14 )
00654 {
00655 if ( fapint_valid_com_telem_char((*rest)[i+11]) &&
00656 fapint_valid_com_telem_char((*rest)[i+12]) )
00657 {
00658 packet->telemetry->val5 = ((*rest)[i+11] - 33) * 91 + (*rest)[i+12] - 33;
00659 }
00660 else
00661 {
00662 free(packet->telemetry);
00663 packet->telemetry = NULL;
00664 return;
00665 }
00666 }
00667
00668
00669 if ( len >= 16 )
00670 {
00671 if ( fapint_valid_com_telem_char((*rest)[i+13]) &&
00672 fapint_valid_com_telem_char((*rest)[i+14]) )
00673 {
00674 tmp = ((*rest)[i+13] - 33) * 91 + (*rest)[i+14] - 33;
00675
00676
00677 sprintf(buf, "%d%d%d%d%d%d%d%d", 0x01 & tmp, 0x02 & tmp, 0x04 & tmp, 0x08 & tmp, 0x10 & tmp, 0x20 & tmp, 0x40 & tmp, 0x80 & tmp);
00678 for ( tmp = 0; tmp < strlen(buf) && tmp < 8; ++tmp )
00679 {
00680 packet->telemetry->bits[tmp] = buf[tmp];
00681 }
00682 }
00683 else
00684 {
00685 free(packet->telemetry);
00686 packet->telemetry = NULL;
00687 return;
00688 }
00689 }
00690
00691
00692 tmp_us = *rest_len;
00693 tmp_str = fapint_remove_part(*rest, tmp_us, i, j+1, rest_len);
00694 free(*rest);
00695 *rest = tmp_str;
00696 }
00697 }
00698
00699
00700
00701 void fapint_init_wx_report(fap_wx_report_t* wx_report)
00702 {
00703 wx_report->wind_gust = NULL;
00704 wx_report->wind_dir = NULL;
00705 wx_report->wind_speed = NULL;
00706 wx_report->temp = NULL;
00707 wx_report->temp_in = NULL;
00708 wx_report->rain_1h = NULL;
00709 wx_report->rain_24h = NULL;
00710 wx_report->rain_midnight = NULL;
00711 wx_report->humidity = NULL;
00712 wx_report->humidity_in = NULL;
00713 wx_report->pressure = NULL;
00714 wx_report->luminosity = NULL;
00715 wx_report->snow_24h = NULL;
00716 wx_report->soft = NULL;
00717 }
00718
00719
00720
00721 void fapint_init_telemetry_report(fap_telemetry_t* telemetry)
00722 {
00723 if ( !telemetry ) return;
00724 telemetry->seq = 0;
00725 telemetry->val1 = 0.0;
00726 telemetry->val2 = 0.0;
00727 telemetry->val3 = 0.0;
00728 telemetry->val4 = 0.0;
00729 telemetry->val5 = 0.0;
00730 memset(telemetry->bits, '?', 8);
00731 }
00732
00733
00734
00735 char* fapint_remove_part(char const* input, unsigned int const input_len,
00736 unsigned int const part_so, unsigned int const part_eo,
00737 unsigned int* result_len)
00738 {
00739 unsigned int i, part_i;
00740 char* result;
00741
00742
00743
00744 if( !input || !input_len || part_so >= input_len || part_eo > input_len || part_so >= part_eo )
00745 {
00746 *result_len = 0;
00747 return NULL;
00748 }
00749
00750
00751 *result_len = input_len - (part_eo - part_so);
00752 if ( *result_len == 0 )
00753 {
00754 return NULL;
00755 }
00756
00757
00758 result = malloc(*result_len+1);
00759 if ( !result )
00760 {
00761 *result_len = 0;
00762 return NULL;
00763 }
00764 part_i = 0;
00765 for ( i = 0; i < input_len; ++i )
00766 {
00767
00768 if ( i < part_so || i >= part_eo )
00769 {
00770 result[part_i] = input[i];
00771 ++part_i;
00772 }
00773 }
00774
00775
00776 result[*result_len] = 0;
00777
00778
00779 return result;
00780 }