@@ -1377,9 +1377,14 @@ static void aprs_mic_e (decode_aprs_t *A, packet_t pp, unsigned char *info, int
13771377
13781378#define isT (c ) ((c) == ' ' || (c) == '>' || (c) == ']' || (c) == '`' || (c) == '\'')
13791379
1380- // Last updated Sept. 2016 for TH-D74A
1380+ // Last Updated Dec. 2021
1381+
1382+ // This does not change very often but I'm wondering if we could simply parse
1383+ // http://www.aprs.org/aprs12/mic-e-types.txt similar to how we use tocalls.txt.
13811384
13821385 if (isT (* pfirst )) {
1386+
1387+ // "legacy" formats.
13831388
13841389 if (* pfirst == ' ' ) { strlcpy (A -> g_mfr , "Original MIC-E" , sizeof (A -> g_mfr )); pfirst ++ ; }
13851390
@@ -1390,6 +1395,8 @@ static void aprs_mic_e (decode_aprs_t *A, packet_t pp, unsigned char *info, int
13901395 else if (* pfirst == ']' && * plast == '=' ) { strlcpy (A -> g_mfr , "Kenwood TM-D710" , sizeof (A -> g_mfr )); pfirst ++ ; plast -- ; }
13911396 else if (* pfirst == ']' ) { strlcpy (A -> g_mfr , "Kenwood TM-D700" , sizeof (A -> g_mfr )); pfirst ++ ; }
13921397
1398+ // ` should be used for message capable devices.
1399+
13931400 else if (* pfirst == '`' && * (plast - 1 ) == '_' && * plast == ' ' ) { strlcpy (A -> g_mfr , "Yaesu VX-8" , sizeof (A -> g_mfr )); pfirst ++ ; plast -= 2 ; }
13941401 else if (* pfirst == '`' && * (plast - 1 ) == '_' && * plast == '"' ) { strlcpy (A -> g_mfr , "Yaesu FTM-350" , sizeof (A -> g_mfr )); pfirst ++ ; plast -= 2 ; }
13951402 else if (* pfirst == '`' && * (plast - 1 ) == '_' && * plast == '#' ) { strlcpy (A -> g_mfr , "Yaesu VX-8G" , sizeof (A -> g_mfr )); pfirst ++ ; plast -= 2 ; }
@@ -1398,11 +1405,15 @@ static void aprs_mic_e (decode_aprs_t *A, packet_t pp, unsigned char *info, int
13981405 else if (* pfirst == '`' && * (plast - 1 ) == '_' && * plast == ')' ) { strlcpy (A -> g_mfr , "Yaesu FTM-100D" , sizeof (A -> g_mfr )); pfirst ++ ; plast -= 2 ; }
13991406 else if (* pfirst == '`' && * (plast - 1 ) == '_' && * plast == '(' ) { strlcpy (A -> g_mfr , "Yaesu FT2D" , sizeof (A -> g_mfr )); pfirst ++ ; plast -= 2 ; }
14001407 else if (* pfirst == '`' && * (plast - 1 ) == '_' && * plast == '0' ) { strlcpy (A -> g_mfr , "Yaesu FT3D" , sizeof (A -> g_mfr )); pfirst ++ ; plast -= 2 ; }
1408+ else if (* pfirst == '`' && * (plast - 1 ) == '_' && * plast == '3' ) { strlcpy (A -> g_mfr , "Yaesu FT5D" , sizeof (A -> g_mfr )); pfirst ++ ; plast -= 2 ; }
1409+ else if (* pfirst == '`' && * (plast - 1 ) == '_' && * plast == '1' ) { strlcpy (A -> g_mfr , "Yaesu FTM-300D" , sizeof (A -> g_mfr )); pfirst ++ ; plast -= 2 ; }
14011410
14021411 else if (* pfirst == '`' && * (plast - 1 ) == ' ' && * plast == 'X' ) { strlcpy (A -> g_mfr , "AP510" , sizeof (A -> g_mfr )); pfirst ++ ; plast -= 2 ; }
1412+
14031413 else if (* pfirst == '`' && * (plast - 1 ) == '(' && * plast == '5' ) { strlcpy (A -> g_mfr , "Anytone D578UV" , sizeof (A -> g_mfr )); pfirst ++ ; plast -= 2 ; }
1414+ else if (* pfirst == '`' ) { strlcpy (A -> g_mfr , "Generic Mic-Emsg" , sizeof (A -> g_mfr )); pfirst ++ ; }
14041415
1405- else if ( * pfirst == '`' ) { strlcpy ( A -> g_mfr , "Mic-Emsg" , sizeof ( A -> g_mfr )); pfirst ++ ; }
1416+ // ' should be used for trackers (not message capable).
14061417
14071418 else if (* pfirst == '\'' && * (plast - 1 ) == '(' && * plast == '8' ) { strlcpy (A -> g_mfr , "Anytone D878UV" , sizeof (A -> g_mfr )); pfirst ++ ; plast -= 2 ; }
14081419
@@ -1412,13 +1423,13 @@ static void aprs_mic_e (decode_aprs_t *A, packet_t pp, unsigned char *info, int
14121423 else if (* pfirst == '\'' && * (plast - 1 ) == ':' && * plast == '4' ) { strlcpy (A -> g_mfr , "SCS GmbH & Co. P4dragon DR-7400 modems" , sizeof (A -> g_mfr )); pfirst ++ ; plast -= 2 ; }
14131424 else if (* pfirst == '\'' && * (plast - 1 ) == ':' && * plast == '8' ) { strlcpy (A -> g_mfr , "SCS GmbH & Co. P4dragon DR-7800 modems" , sizeof (A -> g_mfr )); pfirst ++ ; plast -= 2 ; }
14141425
1415- else if (* pfirst == '\'' ) { strlcpy (A -> g_mfr , "McTrackr" , sizeof (A -> g_mfr )); pfirst ++ ; }
1426+ else if (* pfirst == '\'' ) { strlcpy (A -> g_mfr , "Generic McTrackr" , sizeof (A -> g_mfr )); pfirst ++ ; }
14161427
14171428 else if ( * (plast - 1 ) == '\\' ) { strlcpy (A -> g_mfr , "Hamhud ?" , sizeof (A -> g_mfr )); pfirst ++ ; plast -= 2 ; }
14181429 else if ( * (plast - 1 ) == '/' ) { strlcpy (A -> g_mfr , "Argent ?" , sizeof (A -> g_mfr )); pfirst ++ ; plast -= 2 ; }
14191430 else if ( * (plast - 1 ) == '^' ) { strlcpy (A -> g_mfr , "HinzTec anyfrog" , sizeof (A -> g_mfr )); pfirst ++ ; plast -= 2 ; }
14201431 else if ( * (plast - 1 ) == '*' ) { strlcpy (A -> g_mfr , "APOZxx www.KissOZ.dk Tracker. OZ1EKD and OZ7HVO" , sizeof (A -> g_mfr )); pfirst ++ ; plast -= 2 ; }
1421- else if ( * (plast - 1 ) == '~' ) { strlcpy (A -> g_mfr , "OTHER" , sizeof (A -> g_mfr )); pfirst ++ ; plast -= 2 ; }
1432+ else if ( * (plast - 1 ) == '~' ) { strlcpy (A -> g_mfr , "Unknown OTHER" , sizeof (A -> g_mfr )); pfirst ++ ; plast -= 2 ; }
14221433 }
14231434
14241435/*
@@ -3486,6 +3497,8 @@ time_t get_timestamp (decode_aprs_t *A, char *p)
34863497 time_t ts ;
34873498
34883499 ts = time (NULL );
3500+ // FIXME: use gmtime_r instead.
3501+ // Besides not being thread safe, gmtime could possibly return null.
34893502 ptm = gmtime (& ts );
34903503
34913504 pdhm = (void * )p ;
@@ -4211,9 +4224,7 @@ static void process_comment (decode_aprs_t *A, char *pstart, int clen)
42114224 dw_printf ("%s:%d: %s\n" , __FILE__ , __LINE__ , emsg );
42124225 }
42134226
4214- // TODO: Would like to restrict to even length something like this: ([!-{][!-{]){2,7}
4215-
4216- e = regcomp (& base91_tel_re , "\\|([!-{]{4,14})\\|" , REG_EXTENDED );
4227+ e = regcomp (& base91_tel_re , "\\|(([!-{][!-{]){2,7})\\|" , REG_EXTENDED );
42174228 if (e ) {
42184229 regerror (e , & base91_tel_re , emsg , sizeof (emsg ));
42194230 dw_printf ("%s:%d: %s\n" , __FILE__ , __LINE__ , emsg );
@@ -4411,20 +4422,20 @@ static void process_comment (decode_aprs_t *A, char *pstart, int clen)
44114422
44124423/*
44134424 * Telemetry data, in base 91 compressed format appears as 2 to 7 pairs
4414- * of base 91 digits, surrounded by | at start and end.
4425+ * of base 91 digits, ! thru {, surrounded by | at start and end.
44154426 */
44164427
44174428
44184429 if (regexec (& base91_tel_re , A -> g_comment , MAXMATCH , match , 0 ) == 0 )
44194430 {
44204431
4421- char tdata [30 ]; /* Should be 4 to 14 characters. */
4432+ char tdata [30 ]; /* Should be even number of 4 to 14 characters. */
44224433
4423- //dw_printf("compressed telemetry start=%d, end=%d\n", (int)(match[0].rm_so), (int)(match[0].rm_eo));
4434+ //dw_printf("compressed telemetry start=%d, end=%d\n", (int)(match[0].rm_so), (int)(match[0].rm_eo));
44244435
44254436 substr_se (tdata , A -> g_comment , match [1 ].rm_so , match [1 ].rm_eo );
44264437
4427- //dw_printf("compressed telemetry data = \"%s\"\n", tdata);
4438+ //dw_printf("compressed telemetry data = \"%s\"\n", tdata);
44284439
44294440 telemetry_data_base91 (A -> g_src , tdata , A -> g_telemetry , sizeof (A -> g_telemetry ));
44304441
@@ -4442,6 +4453,8 @@ static void process_comment (decode_aprs_t *A, char *pstart, int clen)
44424453 *
44434454 * It surprised me to see this in a MIC-E message.
44444455 * MIC-E has resolution of .01 minute so it would make sense to have it as an option.
4456+ * We also find an example in http://www.aprs.org/aprs12/mic-e-examples.txt
4457+ * 'abc123R/'123}FFF.FFFMHztext.../A=123456...!DAO! Mv
44454458 */
44464459
44474460 if (regexec (& dao_re , A -> g_comment , MAXMATCH , match , 0 ) == 0 )
@@ -4451,7 +4464,7 @@ static void process_comment (decode_aprs_t *A, char *pstart, int clen)
44514464 int a = A -> g_comment [match [0 ].rm_so + 2 ];
44524465 int o = A -> g_comment [match [0 ].rm_so + 3 ];
44534466
4454- // dw_printf("start=%d, end=%d\n", (int)(match[0].rm_so), (int)(match[0].rm_eo));
4467+ dw_printf ("DAO start=%d, end=%d\n" , (int )(match [0 ].rm_so ), (int )(match [0 ].rm_eo ));
44554468
44564469
44574470/*
@@ -4503,7 +4516,7 @@ static void process_comment (decode_aprs_t *A, char *pstart, int clen)
45034516 */
45044517
45054518/*
4506- * Here is an interesting case .
4519+ * Here are a couple situations where it is seen .
45074520 *
45084521 * W8SAT-1>T2UV0P:`qC<0x1f>l!Xu\'"69}WMNI EDS Response Unit #1|+/%0'n|!w:X!|3
45094522 *
@@ -4520,13 +4533,26 @@ static void process_comment (decode_aprs_t *A, char *pstart, int clen)
45204533 * Comment earlier points out that MIC-E format has resolution of 0.01 minute,
45214534 * same as non-compressed format, so the DAO does work out, after thinking
45224535 * about it for a while.
4536+ * We also find a MIC-E example with !DAO! here: http://www.aprs.org/aprs12/mic-e-examples.txt
4537+ *
4538+ * Another one:
4539+ *
4540+ * KS4FUN-12>3X0PRU,W6CX-3,BKELEY,WIDE2*:`2^=l!<0x1c>+/'"48}MT-RTG|%B%p'a|!wqR!|3
4541+ *
4542+ * MIC-E, Red Cross, Special
4543+ * N 38 00.2588, W 122 06.3354
4544+ * 0 MPH, course 100, alt 108 ft
4545+ * MT-RTG comment
4546+ * |%B%p'a| Seq=397, A1=443, A2=610
4547+ * !wqR! DAO
4548+ * |3 Byonics TinyTrack3
4549+ *
45234550 */
45244551
45254552/*
45264553 * The spec appears to be wrong. It says '}' is the maximum value when it should be '{'.
45274554 */
45284555
4529-
45304556 if (isdigit91 (a )) {
45314557 A -> g_lat += (a - B91_MIN ) * 1.1 / 600000.0 * sign (A -> g_lat );
45324558 }
0 commit comments