From c13c9806f957ebc675462737f4b328d3ab89e028 Mon Sep 17 00:00:00 2001
From: guowenxue <guowenxue@gmail.com>
Date: Mon, 10 Jul 2023 17:29:22 +0800
Subject: [PATCH] update gpsd.c

---
 gpsd/gpsd.c |  245 +++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 245 insertions(+), 0 deletions(-)

diff --git a/gpsd/gpsd.c b/gpsd/gpsd.c
new file mode 100644
index 0000000..61356f1
--- /dev/null
+++ b/gpsd/gpsd.c
@@ -0,0 +1,245 @@
+/*********************************************************************************
+ *      Copyright:  (C) 2023 LingYun IoT System Studio
+ *                  All rights reserved.
+ *
+ *       Filename:  gpsd.c
+ *    Description:  This file is GPS location parser program
+ *
+ *        Version:  1.0.0(07/10/23)
+ *         Author:  Guo Wenxue <guowenxue@gmail.com>
+ *      ChangeLog:  1, Release initial version on "07/10/23 09:49:55"
+ *
+ ********************************************************************************/
+
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "logger.h"
+#include "comport.h"
+#include "util_proc.h"
+
+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);
+
+static inline void banner(const char *progname)
+{
+    printf("%s program Version v1.0.0 Build on (%s)\n", progname, __DATE__);
+    printf("Copyright (C) 2023 LingYun IoT System Studio.\n");
+}
+
+static void program_usage(const char *progname)
+{
+    banner(progname);
+
+    printf("Usage: %s [OPTION]...\n", progname);
+    printf(" %s is a MQTT subscribe daemon program to control relay. \n", progname);
+
+    printf("\nMandatory arguments to long options are mandatory for short options too:\n");
+    printf(" -D[device  ]  Set GPS connect serial port device\n");
+    printf(" -d[debug   ]  Running in debug mode\n");
+    printf(" -l[level   ]  Set the log level as [0..%d]\n", LOG_LEVEL_MAX-1);
+    printf(" -h[help    ]  Display this help information\n");
+    printf(" -v[version ]  Display the program version\n");
+
+    return;
+}
+
+int main (int argc, char **argv)
+{
+    const char             *progname=NULL;
+    int                     opt = 0;
+    int                     rv = 0;
+    int                     debug = 0;
+    char                    pid_file[64] = { 0 }; /*   The file used to record the PID */
+    char                   *log_file = "/tmp/gpsd.log";
+    int                     log_level = LOG_LEVEL_INFO;
+    int                     log_size = 10;
+
+    char                    buf[4096];
+    char                   *dev=NULL;
+    comport_t               comport;
+    gps_fix_t               info;
+
+    struct option long_options[] = {
+        {"device", required_argument, NULL, 'D'},
+        {"debug", no_argument, NULL, 'd'},
+        {"level", required_argument, NULL, 'l'},
+        {"version", no_argument, NULL, 'v'},
+        {"help", no_argument, NULL, 'h'},
+        {NULL, 0, NULL, 0}
+    };
+
+    progname = basename(argv[0]);
+    /*  Parser the command line parameters */
+    while ((opt = getopt_long(argc, argv, "D:dl:vh", long_options, NULL)) != -1)
+    {
+        switch (opt)
+        {
+            case 'D':  /*  Set serial port device */
+                dev = optarg;
+                break;
+
+            case 'd': /*  Set debug running */
+                debug = 1;
+                log_file = "console";
+                log_level = LOG_LEVEL_DEBUG;
+                log_size = ROLLBACK_NONE;
+                break;
+
+            case 'l': /*  Set the log level */
+                rv = atoi(optarg);
+                log_level = rv>LOG_LEVEL_MAX ? LOG_LEVEL_MAX-1 : rv;
+                break;
+
+            case 'v':  /*  Get software version */
+                banner(progname); /*  Defined in version.h */
+                return EXIT_SUCCESS;
+
+            case 'h':  /*  Get help information */
+                program_usage(progname);
+                return 0;
+
+            default:
+                break;
+        } /*   end of "switch(opt)" */
+    }
+
+    if( !dev )
+    {
+        program_usage(progname);
+        return 0;
+    }
+
+    if( (rv=log_open(log_file, log_level, log_size, LOG_LOCK_DISABLE)) < 0 )
+    {
+        fprintf(stderr, "open logger failed, rv=%d\n", rv);
+        return 1;
+    }
+
+    if( !debug )
+    {
+        snprintf(pid_file, sizeof(pid_file), "/var/run/%s.pid", progname);
+        log_info("check program running in daemon or not by pidfile [%s]\n", pid_file);
+        if( check_daemon_running(pid_file) )
+        {
+            printf("Programe already running, exit now.\n");
+            return 3;
+        }
+
+        if( set_daemon_running(pid_file) < 0 )
+        {
+            printf("Programe already running, exit now.\n");
+            return 3;
+        }
+    }
+
+    if( (rv=comport_open(&comport, dev, 4800, "8N1N")) < 0 )
+    {
+        log_error("Open serial port \"%s\" failed, rv=%d\n", dev, rv);
+        return 2;
+    }
+    log_info("Open serial port \"%s\" successfully\n", dev);
+
+    while(1)
+    {
+        memset(buf, 0, sizeof(buf));
+        rv = comport_recv(&comport, buf, sizeof(buf), 3000);
+        if( rv > 0 )
+        {
+            proc_gprmc(buf, strlen(buf), &info);
+        }
+    }
+
+    comport_close(&comport);
+    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 )
+    {
+        log_error("Invalid input arguments\n");
+        return -1;
+    }
+
+    log_trace("GPS receive raw data\n:%s\n", buf);
+
+    if( !(ptr_start=strstr(buf, "$GPRMC")) )
+    {
+        log_warn("$GPRMC keywords not matched\n");
+        return -2;
+    }
+
+    if( !(ptr_end=strchr(ptr_start, 0x0D)) )
+    {
+        log_warn("$GPRMC data not integrated\n");
+    }
+
+    *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' )
+    {
+        log_info("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' )
+    {
+        log_info("NMEA0183: Invalid data\n");
+    }
+
+    return 0;
+}

--
Gitblit v1.9.1