APUE course source code
guowenxue
2 days ago 68826376ee5f47783c644c6604f4411ec747cd7e
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
/*********************************************************************************
 *      Copyright:  (C) 2023 LingYun IoT System Studio.
 *                  All rights reserved.
 *
 *       Filename:  pack_gps.c
 *    Description:  This file is GPS NMEA format string parser example
 *
 *        Version:  1.0.0(2023年07月10日)
 *         Author:  Guo Wenxue <guowenxue@gmail.com>
 *      ChangeLog:  1, Release initial version on "2023年07月10日 17时21分35秒"
 *
 ********************************************************************************/
 
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
 
#define GPS_RAWDATA  "\
$GPGSA,A,3,18,05,15,24,23,13,29,,,,,,2.2,1.1,1.9*3C\r\n\
$GPRMC,091859.000,A,3029.6909,N,11423.6327,E,0.23,200.08,100723,,,A*65\r\n\
$GPGGA,091900.000,3029.6909,N,11423.6326,E,1,07,1.1,28.2,M,-13.7,M,,0000*40\r\n"
 
typedef struct gps_fix_s
{
    char       time[32];  /* GPS UTC time, formt: hhmmss */
    char       status;    /* A: Valid  V:Invalid */
    float      latitude;  /* Latitude */
    char       lat;       /* N: North  S: South */
    float      longitude; /* Longitude */
    char       lon;       /* E: East   W: West */
    float      speed;     /* Speed over ground, meters/sec */
    float      track;     /* Course made good (relative to true north) */
} gps_fix_t;
 
int proc_gprmc(char *buf, int size, gps_fix_t *info);
 
int main (int argc, char **argv)
{
    char       buf[] = GPS_RAWDATA;
    gps_fix_t   info;
 
    proc_gprmc(buf, strlen(buf), &info);
 
    return 0;
}
 
/*
 * $GPRMC,024216.000,A,3029.6651,N,11423.6251,E,0.08, 156.95,100723,,,A*65
 * 1     024216.000    UTC time format: HHMMSS, 10:42:16(BeiJing)
 * 2     A             Status of Fix:
 *                      A = Autonomous, valid;
 *                      D = Differential, valid;
 *                      V = invalid
 *
 * 3,4   3029.6651,N   Latitude format: ddmm.mmmm, Latitude 30 deg. 29.6651 min North
 * 5,6   11423.6251,E  Longitude: dddmm.mmmm, Longitude 114 deg. 23.6251 min East
 * 7     0.08          Speed over ground, Knots
 * 8     156.95        Course Made Good, True north
 * 9     100723        Date of fix ddmmyy. 2023-07-10
 * 10,11 ,,            Magnetic variation
 * 12    A             FAA mode indicator (NMEA 2.3 and later)
 *                      A=autonomous,
 *                      D=differential,
 *                      E=Estimated,
 *                      M=Manual input mode,
 *                      N=not valid,
 *                      S=Simulator,
 *                      V=Valid
 * 13   *68            mandatory nmea_checksum
 */
 
#define DD(s)   ((int)((s)[0]-'0')*10+(int)((s)[1]-'0'))
int proc_gprmc(char *buf, int size, gps_fix_t *info)
{
    char           *ptr_start=NULL;
    char           *ptr_end=NULL;
    char            hhmmss[12]={0x0};
    char            ddmmyy[12]={0x0};
 
    if( !buf || size<=0 || !info )
    {
        printf("Invalid input arguments\n");
        return -1;
    }
 
    printf("GPS receive raw data:\n%s\n", buf);
 
    if( !(ptr_start=strstr(buf, "$GPRMC")) )
    {
        printf("$GPRMC keywords not matched\n");
        return -2;
    }
 
    if( !(ptr_end=strchr(ptr_start, 0x0D)) )
    {
        printf("$GPRMC data not integrated\n");
        return -3;
    }
 
    *ptr_end = '\0';
 
    memset(info, 0, sizeof(*info));
    sscanf(ptr_start, "$GPRMC,%[^,],%c,%f,%c,%f,%c,%f,%f,%[^,]",
            hhmmss, &info->status, &info->latitude, &info->lat,
            &info->longitude, &info->lon, &info->speed, &info->track, ddmmyy);
 
    snprintf(info->time, sizeof(info->time), "%04d-%02d-%02d %02d:%02d:%02d",
            DD(ddmmyy+4)+2000, DD(ddmmyy+2), DD(ddmmyy),
            DD(hhmmss)+8, DD(hhmmss+2), DD(hhmmss+4));
 
    if( info->status == 'A' )
    {
        printf("NMEA0183: %s lat=%.2f(%c) lon=%.2f(%c) speed=%.2f, track=%.2f\n",
                info->time, info->latitude, info->lat,
                info->longitude, info->lon, info->speed, info->track);
    }
    else if( info->status == 'V' )
    {
        printf("NMEA0183: Invalid data\n");
    }
 
    return 0;
}