GPS NMEA Frames via Serial

The built-in GPS Function is TCP/IP only. If you want to retrieve the GPS NMEA frames over the serial interface of a Netmodule Router you can use this SDK script.

Script Summary

This Script connects to the GPS server via tcp. The NMEA Frames will be startet by the request “R” and will be then written to the serial interface.

The default serial parameter are 115200 8N1 (8 databit, no parity, 1 stop bit, no flow controll). This parameter can be configured at the begining of the script.

Pre Requierments

To use this script you need to enable the GNSS Interface on the Router to your needs. Please use the “raw-mode” with this SDK script.

Also assign the serial interface to the SDK

Installation

Detailed step by step instructions how to install a sdk script can be found on this wiki page

Please combine this script with the “system-startup” trigger to a job

This script does not need any configuration, but you can define the serial parameter to your needs:

/* Serial Baud Rate 9600, 19200, 38400, 57600, 115200 */
SER_SPEED=115200;
/*  number of data bits (5, 6, 7, 8) */
SER_DATABIT=8;
/*  number of stop bits (1, 2) */
SER_STOPBIT=1;
/* parity (0=no parity, 1=odd parity, 2=even parity) */
SER_PARITY=0;
/*  flow control (0=none, 1=xon/xoff, 2=hardware) */
SER_FLOW=0;
/*  name of the Serial Interface (Only changed if your device has more then one serial Interface (NB3710) */
DEV = "SERIAL1";

Testing

To be sure the script is running you can take a look on the System Log and watch for outputs like:

Apr 23 00:53:41 NB2700 user.info sdkhost[2283]: testrun: starting serial
Apr 23 00:53:42 NB2700 user.info sdkhost[2283]: testrun: Connecting to GPS daemon
Apr 23 00:53:42 NB2700 user.info sdkhost[2283]: testrun: Requesting raw NMEA stream
Apr 23 00:53:42 NB2700 user.info sdkhost[2283]: testrun: Successfully connected to GPS daemon
Apr 23 00:53:42 NB2700 user.info sdkhost[2283]: testrun: Processing NMEA data
Apr 23 00:53:42 NB2700 user.info sdkhost[2283]: testrun: Unable to send message to via Serial
Apr 23 00:54:08 NB2700 user.info sdkhost[2283]: testrun: starting serial
Apr 23 00:54:09 NB2700 user.info sdkhost[2283]: testrun: Connecting to GPS daemon
Apr 23 00:54:09 NB2700 user.info sdkhost[2283]: testrun: Requesting raw NMEA stream
Apr 23 00:54:09 NB2700 user.info sdkhost[2283]: testrun: Successfully connected to GPS daemon
Apr 23 00:54:09 NB2700 user.info sdkhost[2283]: testrun: Processing NMEA data

The Script

gps-to-serial.are
 
/* DESC: This script sends the local GPS NMEA stream (incl. serial/checksum) to a remote UDP server.
 * Copyright (C) 2013-2015 NetModule AG, Switzerland
 */
 
/* Options to configure by user*/
/* Serial Baud Rate 9600, 19200, 38400, 57600, 115200 */
SER_SPEED=115200;
/*  number of data bits (5, 6, 7, 8) */
SER_DATABIT=8;
/*  number of stop bits (1, 2) */
SER_STOPBIT=1;
/* parity (0=no parity, 1=odd parity, 2=even parity) */
SER_PARITY=0;
/*  flow control (0=none, 1=xon/xoff, 2=hardware) */
SER_FLOW=0;
/*  name of the Serial Interface (Only changed if your device has more then one serial Interface (NB3710) */
DEV = "SERIAL1";
 
 
 
void usage() 
{
    nb_syslog("Usage: gps-udp-client.are <server> <port>");
    exit(1);
}
 
 
int start_serial() {
 
    /* check serial port config */
    status = nb_config_get("serial.0.status");
    if (status != "2") {
        nb_syslog("Serial port is not enabled for us");
        return -1;
    }
 
    /* set attributes */
    rc = nb_serial_setattr(DEV, SER_SPEED, SER_DATABIT, SER_STOPBIT, SER_PARITY, SER_FLOW);
    if (rc != 0) {
        nb_syslog("ERROR: unable to set serial attributes (rc %d)", rc);
        return -1;
    }
 
    /* open serial port */
    fd = nb_serial_open(DEV);
    if (fd < 0) {
        return -1;
    }
 
    return fd;
}
 
int connect_gpsd ()
{
    for (attempt = 0; attempt < 60; attempt++) {
        sleep(1);
 
        sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
        if (sock < 0) {
            nb_syslog("Unable to create socket");
            continue;
        }
        nb_syslog("Connecting to GPS daemon");
        if (connect(sock, "127.0.0.1", 2947) < 0){
            nb_syslog("Could not connect to GPS daemon");
            close(sock);
            continue;
        }
        nb_syslog("Requesting raw NMEA stream");
        if (send(sock, "R\n") < 0) {
            nb_syslog("Unable to request raw NMEA stream");
            close(sock);
            continue;
        }
 
        nb_syslog("Successfully connected to GPS daemon");
        return sock;
    }
 
    return -1;
}
 
 
SERVER = trim((string) argv[1]);
PORT = (int) argv[2];
 
SERIAL = struct_get(nb_status("system"), "SERIAL_NUMBER");
if (SERIAL == "") {
    nb_syslog("Unable to obtain serial number");
    exit(1);
}
 
nb_syslog("starting serial");
serial_fd = start_serial();
if (serial_fd < 0 ) {
    nb_syslog("Could not start serial, exiting");
    exit(1);
}
 
gpsd = connect_gpsd();
if (gpsd < 0) {
    nb_syslog("Could not start gpsd socket, exiting");
    exit(1);
}
 
/* process NMEA stream */
nb_syslog("Processing NMEA data");
 
while (1) {
    /* wait for socket data  */
    rv = select(gpsd, 3);
    if (rv > 0) {
        data = recv(gpsd);
        len = strlen(data);
    } else if (rv < 0) {
        nb_syslog("select failed");
        len = -1;
    } else {
        /* nothing received */
        continue;
    } 
    if (len <= 0) {
        nb_syslog("Receive failed, re-connecting to GPS daemon");
        close(gpsd);
        gpsd = connect_gpsd();
        if (gpsd < 0) {
            exit(1);
        }
    } else {
        str = strcat("PNMID,", SERIAL);
        chars = explode(str);
 
        checksum = 0;
        for (i = 0; i < length(chars); i++) {
            c = ord(chars[i]);
            checksum ^= c;
        }
        sentence = sprintf("$%s*%02X\r\n", str, checksum);
        data = strcat(data, sentence);
        len = strlen(data);
        nb_syslog("len: %i", len);
        if (len > 0) {
            sent = write(serial_fd, data, len);
            if (sent != len) {
                nb_syslog("Unable to send message via Serial, sent: %i, len: %i",sent, len);
            }
        }
    }
 
 
}
 
close(gpsd);
close(serial_fd);
 
exit(0);