Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revisionPrevious revision
Next revision
Previous revision
app-notes:send-the-local-gps-nmea-stream-to-a-remote-udp-server [2025/11/05 13:47] – [1. Set up the SDK script on the router] grayapp-notes:send-the-local-gps-nmea-stream-to-a-remote-udp-server [2025/11/05 14:32] (current) – [2. Additional information] gray
Line 62: Line 62:
  
 ############################################################################### ###############################################################################
-DEBUG=flase;      # Enable debugging with true or disable with false +DEBUG=false;      # Enable debugging with true or disable with false 
-DEBUGALL=flase;   # Enable debugging with true or disable with false+DEBUGALL=false;   # Enable debugging with true or disable with false
 ############################################################################### ###############################################################################
  
Line 257: Line 257:
  
 Again, start by assigning a ''name'' to the SDK process. Use the ''“event-based”'' option as the trigger type for this script. Select the ''“sdk-startup”'' event from the list. Why do we use these settings for the script? The script was created as an endless script. The commands are controlled and executed in the script. Errors are output and the program is then terminated. The event starts the script when the daemon of the SDK program is started by the router. This is also advantageous if the watchdog restarts the SDK daemon on the router. In this case, the script is also reactivated.  The ''“Apply”'' button saves the changes back to the router. Again, start by assigning a ''name'' to the SDK process. Use the ''“event-based”'' option as the trigger type for this script. Select the ''“sdk-startup”'' event from the list. Why do we use these settings for the script? The script was created as an endless script. The commands are controlled and executed in the script. Errors are output and the program is then terminated. The event starts the script when the daemon of the SDK program is started by the router. This is also advantageous if the watchdog restarts the SDK daemon on the router. In this case, the script is also reactivated.  The ''“Apply”'' button saves the changes back to the router.
 +
 +----
 +
 +In the last step, we activate the SDK script on the router. 
 +
 +{{:app-notes:gnss_sdk_job.png?950|}}
 +
 +Again, enter the ''name'' for the SDK process first. If you want to activate the first SDK script on the router, the two fields ''“Trigger”'' and ''"Script"'' are already filled with the options you set up earlier. If you already have multiple scripts, you must select the correct option ''(Trigger and Script)'' from the pull-down menu. As before, click ''“Apply”'' to apply the setting to the router. In this case, the SDK script is also activated. Two arguments are required for the GPS_Tracking script: an IP address from the server and a UDP port. In this example, the ''IP address 192.168.1.1'' and '' UDP port 20000'' were used.
 +
 +----
 +{{:app-notes:gnss_sdk_status.png?950|}}
 +
 +Using the Administration option under ''point 1'', you can view information under the Status tab, ''point 2'', to see whether the SDK script has started correctly and is running without errors.
 +
 +----
 +
 +
 +===== - Additional information =====
 +
 +++++show code| 
 +<code – GPS_TRACKING.are>
 +/* DESC: This script sends the local GPS NMEA stream to a remote UDP server
 + * (including device identity).
 + * In addition, a Telit module is used to provide the GPRMC frame from the
 + * GNSS data block using a regular expression.
 + * Copyright (C) 2013-2025 NetModule AG, Switzerland
 + */
 +
 +###############################################################################
 +DEBUG=false;      # Enable debugging with true or disable with false
 +DEBUGALL=false;   # Enable debugging with true or disable with false
 +###############################################################################
 +
 +release_point = 0;
 +
 +void usage()
 +{
 +    nb_syslog("usage: gps-broadcast.are <server> <port>");
 +    printf("No server IP address or port was entered <server> <port>\n");
 +    exit(1);
 +}
 +
 +if (argc < 2) {
 +    usage();
 +}
 +
 +SERVER = trim((string) argv[1]);
 +PORT = (int) argv[2];
 +
 +int gpsd_request (int fd)
 +{
 +    nb_syslog("Requesting NMEA stream");
 +
 +    if (send(fd, "R\n") != 2) {
 +        nb_syslog("ERROR: cannot send to gpsd");
 +        return -1;
 +    }
 +
 +    return 0;
 +}
 +
 +int gpsd_init ()
 +{
 +    /* connect to gpsd */
 +    fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
 +    if (fd < 0) {
 +        nb_syslog("ERROR: unable to open socket to gpsd");
 +        return -1;
 +    }
 +
 +    if (connect(fd, "127.0.0.1", 2947) < 0){
 +        nb_syslog("ERROR: unable to connect to gpsd");
 +        close(fd);
 +        return -1;
 +    }
 +
 +    if (gpsd_request(fd) != 0) {
 +        close(fd);
 +        return -1;
 +    }
 +
 +    return fd;
 +}
 +
 +void gpsd_uninit (int fd)
 +{
 +    if (fd >= 0) {
 +        close(fd);
 +    }
 +}
 +
 +int server_init ()
 +{
 +    /* open UDP server socket */
 +    fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
 +    if (fd < 0) {
 +        nb_syslog("ERROR: unable to open server socket");
 +        return -1;
 +    } else {
 +        return fd;
 +    }
 +}
 +
 +void server_uninit (int fd)
 +{
 +    if (fd >= 0) {
 +        close(fd);
 +    }
 +}
 +
 +
 +int gpsd_process (int gpsd, int server)
 +{
 +    /* process NMEA stream */
 +    nb_syslog("Processing NMEA data");
 +    while(1) {
 +        /* wait for client socket data  */
 +        rv = select(gpsd, 3);
 +        if (rv == -1) {
 +            nb_syslog("ERROR: select failed");
 +            return -1;
 +        } else if (rv == 0) {
 +            /* nb_syslog("nothing received"); */
 +            continue;
 +        }
 +        data = recv(gpsd);
 +        if(DEBUG || DEBUGALL)printf("The raw data frames from the GNSS module:\n%s\n",data);
 +        status = nb_status("wwan");
 +        info = struct_get(status, "MOBILE1_MODULE_INFO");
 +        info = right(info,strlen(info)-14);
 +        len = strlen(info);
 +        temp = len - 6;
 +        info = left(info,strlen(info)-temp);
 +        if(DEBUGALL)printf("Querying the modem module in the router: %s\n", info);
 +        if (info == "Telit "){
 +          if(DEBUGALL)printf("A Telit module was installed!\n\n");
 +          len = strlen(data);
 +          if (len > 200){
 +            if(DEBUG || DEBUGALL)printf("The GNSS data block is larger than 200 bytes: %s bytes\n",len);
 +            data_gprmc = pcre_compile("\\$GPRMC.*\\r\\n?", 0);
 +            m = pcre_exec( data_gprmc, data, 0);
 +            len = strlen(m[0]);
 +            if(DEBUGALL)printf("Check whether the GPRMC frame is present in the GNSS data block: %s bytes\n",len);
 +            if (len != 0){
 +               if(DEBUG || DEBUGALL)printf("The data block is searched for the GPRMC frame using a regex rule:\n%s\n", m[0]);
 +              release_point = 1;
 +              } else {
 +                  if(DEBUGALL)printf("The GPRMC frame does not contain GNSS data blocks: %s bytes\n",len);
 +                }
 +          }
 +        }
 +        if (strlen(data) == 0) {
 +            nb_syslog("ERROR: no NMEA data");
 +            return -1;
 +        }
 +
 +        status = nb_status("system");
 +        serial = struct_get(status, "SERIAL_NUMBER");
 +        sentence = strcat("PNMID,", serial);
 +        sentenceLength = strlen(sentence);
 +        sentenceArray = explode(sentence);
 +
 +        checksum = 0;
 +        for (i = 0; i < sentenceLength; i++) {
 +            currentChar = ord(sentenceArray[i]);
 +            checksum ^= currentChar;
 +        }
 +
 +        checksum = sprintf("%02X",checksum);
 +        nmsentence = strcat("$", sentence , "*", checksum ,"\r\n");
 +        if (release_point == 0){
 +          data = strcat(data, nmsentence);
 +          if(DEBUG || DEBUGALL)printf("The GNSS frame has been extended with the serial number from the router:\n%s\n",data);
 +        }
 +        if (release_point == 1){
 +          if(DEBUG || DEBUGALL)printf("Approval for the GPRMC frame: %s\n",release_point);
 +          m = strcat(m[0], nmsentence);
 +          if(DEBUG || DEBUGALL)printf("The GPRMC frame has been extended with the serial number from the router:\n%s\n",m);
 +          release_point = 0;
 +          data = m;
 +        }
 +        len = strlen(data);
 +        if (len <= 0) continue;
 +        sent = sendto(server, data, SERVER, PORT);
 +        if(DEBUG || DEBUGALL)printf("This GNSS data frame is sent: %s bytes\n\n\n",sent);
 +        if (sent != len) {
 +            nb_syslog("ERROR: unable to send to %s:%d", SERVER, PORT);
 +            return -1;
 +        }
 +    }
 +
 +    return 0;
 +}
 +
 +/* main */
 +
 +while (1) {
 +    nb_syslog("Initializing connection to gpsd");
 +    gpsd = gpsd_init();
 +    server = server_init();
 +
 +    if (gpsd >= 0 && server >= 0) {
 +        gpsd_process(gpsd, server);
 +    }
 +
 +    server_uninit(server);
 +    gpsd_uninit(gpsd);
 +    sleep(5);
 +}
 +exit(0);
 +</code>
 +++++
 +
 +----
 +