/* 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=flase; # Enable debugging with true or disable with false
DEBUGALL=flase; # 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);