From de34ac51b9af4702d386eb22ffb5daa2977ae0e6 Mon Sep 17 00:00:00 2001 From: Tim Savage Date: Tue, 22 Jun 2010 01:13:34 +1000 Subject: [PATCH] Added support for optional time deltas in nmea logs. Added replay script to replay logs via named pipe. --- examples/log_replay.py | 100 ++++++++++++++++++++++++++++++++++++++++++++++++ src/gypsy-client.c | 33 ++++++++++++++++ src/main.c | 2 + 3 files changed, 135 insertions(+), 0 deletions(-) create mode 100755 examples/log_replay.py diff --git a/examples/log_replay.py b/examples/log_replay.py new file mode 100755 index 0000000..a1d5900 --- /dev/null +++ b/examples/log_replay.py @@ -0,0 +1,100 @@ +#!/usr/bin/env python +# +# A simple tool for playback of Gypsy NMEA logs via a named pipe. +# +# Author: Tim Savage +# Copyright (C) 2010 +# +# This program is free software; you can redistribute it and/or modify it under +# the terms of the GNU General Public License as published by the Free Software +# Foundation; either version 2 of the License, or (at your option) any later +# version. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more +# details. +# +# You should have received a copy of the GNU General Public License along with +# this program; if not, write to the Free Software Foundation, Inc., 59 Temple +# Place - Suite 330, Boston, MA 02111-1307, USA. +# +import os +import sys +import time +import optparse + + +def work_loop(log, pipe, options): + # Stream data to client + while True: + data = log.readline() + delay = options.delay + if not data: + # Rewind to start of log + log.seek(0) + else: + # Check for a comment + if data.startswith('#'): continue + + # Handle the plain case + if not options.plain: + delay, data = data.split(':', 2) + try: + delay = float(delay) + except ValueError: + continue + + time.sleep(delay) + pipe.write(data) + pipe.flush() + + +def get_options(): + p = optparse.OptionParser() + p.add_option('-p', '--pipe', default='/tmp/gypsy', + help='path to named pipe') + p.add_option('', '--plain', action='store_true', default=False, + help="file does not contain time deltas") + p.add_option('', '--delay', type='float', default=0.2, + help="delay between plain messages") + return p.parse_args() + + +def main(): + options, args = get_options() + + if len(args) != 1: + print >> sys.stderr, "Missing file argument." + sys.exit(2) + + log_file = args[0] + + try: + log = open(log_file, 'r') + except IOError: + print >> sys.stderr, "File not found: ", log_file + sys.exit(1) + + print "Waiting for Gypsy on named pipe:", options.pipe + try: + pipe = open(options.pipe, 'w') + except IOError: + print >> sys.stderr, "Unable to open pipe" + sys.exit(1) + + print "Streaming data..." + try: + work_loop(log, pipe, options) + except KeyboardInterrupt: + pass + except IOError: + print "Gypsy disconnected." + finally: + # Clean up + log.close() + pipe.close() + + +if __name__ == '__main__': + main() diff --git a/src/gypsy-client.c b/src/gypsy-client.c index 2312d7b..2a38b2a 100644 --- a/src/gypsy-client.c +++ b/src/gypsy-client.c @@ -78,6 +78,7 @@ typedef enum { /* Defined in main.c */ extern char* nmea_log; +extern gboolean log_deltas; #define READ_BUFFER_SIZE 1024 #define SPEED_TIMEOUT 1000 @@ -91,6 +92,8 @@ typedef struct _GypsyClientPrivate { GIOChannel *channel; /* The channel we talk to the GPS on */ GIOChannel *debug_log; /* The channel to write the NMEA to, or NULL if debugging is off */ + GTimer *debug_delta; /* A timer to log deltas between NMEA messages */ + guint32 error_id, connect_id, input_id; @@ -242,6 +245,11 @@ shutdown_connection (GypsyClient *client) priv->debug_log = NULL; } + if (priv->debug_delta) { + g_timer_destroy (priv->debug_delta); + priv->debug_delta = NULL; + } + priv->chars_in_buffer = 0; #ifdef ENABLE_N810 @@ -253,6 +261,21 @@ shutdown_connection (GypsyClient *client) #endif /* ENABLE_N810 */ } +static void +write_log_delta(GypsyClientPrivate *priv) +{ + char delta_buff[10]; + int delta_len; + //gulong microseconds; + + gdouble delta = g_timer_elapsed (priv->debug_delta, NULL); + g_timer_reset (priv->debug_delta); + + delta_len = g_snprintf (delta_buff, 10, "%f:", delta); + g_io_channel_write_chars (priv->debug_log, delta_buff, + delta_len, NULL, NULL); +} + static gboolean gps_channel_error (GIOChannel *channel, GIOCondition condition, @@ -301,6 +324,9 @@ gps_channel_garmin_input (GIOChannel *channel, &error); if (priv->debug_log) { + if (priv->debug_delta) { + write_log_delta(priv); + } g_io_channel_write_chars(priv->debug_log, buf, chars_read, NULL, NULL); } @@ -438,6 +464,9 @@ gps_channel_input (GIOChannel *channel, NULL); if (priv->debug_log) { + if (priv->debug_delta) { + write_log_delta(priv); + } g_io_channel_write_chars (priv->debug_log, buf, chars_read, NULL, NULL); } @@ -812,6 +841,10 @@ gypsy_client_start (GypsyClient *client, } g_io_channel_set_encoding (priv->debug_log, NULL, NULL); g_io_channel_set_buffered (priv->debug_log, FALSE); + + if (log_deltas) { + priv->debug_delta = g_timer_new (); + } } /* Set up the IO Channel */ diff --git a/src/main.c b/src/main.c index 6cc0e26..0f4ba7b 100644 --- a/src/main.c +++ b/src/main.c @@ -47,6 +47,7 @@ static GMainLoop *mainloop; /* This is a bit ugly, but it works */ char* nmea_log = NULL; +gboolean log_deltas = FALSE; static void gypsy_terminate (GObject *object, @@ -101,6 +102,7 @@ main (int argc, GOptionEntry entries[] = { { "nmea-log", 0, 0, G_OPTION_ARG_FILENAME, &nmea_log, "Log NMEA data to FILE.[device]", "FILE" }, + { "log-delta", 0, 0, G_OPTION_ARG_NONE, &log_deltas, "Log a time delta with NMEA data", NULL }, { "no-daemon", 0, 0, G_OPTION_ARG_NONE, &become_daemon, "Don't become a daemon", NULL }, { "pid-file", 0, 0, G_OPTION_ARG_FILENAME, &user_pidfile, "Specify the location of a PID file", "FILE" }, { NULL } -- 1.7.0.4