Aaah, so these are files created on a device with a removable memory card or is mountable on a host computer and not files created by some Windows software.  That does indeed make it less likely that they'll be "fixed".  Thanx for that clarification.

I've applied this unchanged.   Thanx for the improvements.

RJL

On Sat, Apr 18, 2009 at 11:35 AM, Tal <tal.bav@gmail.com> wrote:
I did some changes and uploaded the patch to
http://sourceforge.net/tracker/?func=detail&aid=2772764&group_id=58972&atid=489477.
I hope it's OK.

Tal

On Sat, Apr 18, 2009 at 6:36 AM, Robert Lipe <robertlipe@gpsbabel.org> wrote:
This format came up before on the list and we all laughed at how goofy it was and were sure they'd fix the bug that created these silly files.  Guess not.

If you can provide some sample test files that are exercised by the 'testo' script and some doc, we'll gladly fold this in.

Thanx!
RJL

On Fri, Apr 10, 2009 at 1:09 PM, Tal <tal.bav@gmail.com> wrote:
Hello,

This patch reads the strange v900 csv format (fields are padded with nulls).
The patch does not support waypoints, because I do not have an example
of a file with waypoints.
I do not own a device, I just play from time to time with my a friend's unit.


Tal



diff -Nurp gpsbabel-1.3.6.original/Makefile.in gpsbabel-1.3.6.v900_2/Makefile.in
--- gpsbabel-1.3.6.original/Makefile.in    2008-11-05 01:23:11.000000000 +0200
+++ gpsbabel-1.3.6.v900_2/Makefile.in    2009-04-10 20:47:24.000000000 +0300
@@ -61,7 +61,7 @@ ALL_FMTS=$(MINIMAL_FMTS) gtm.o gpsutil.o
     ggv_log.o g7towin.o garmin_gpi.o lmx.o random.o xol.o dg-100.o \
     navilink.o mtk_logger.o ik3d.o osm.o destinator.o exif.o vidaone.o \
     igo8.o gopal.o humminbird.o mapasia.o gnav_trl.o navitel.o ggv_ovl.o \
-    jtr.o sbp.o mmo.o skyforce.o
+    jtr.o sbp.o mmo.o skyforce.o v900.o

 FMTS=@FMTS@

diff -Nurp gpsbabel-1.3.6.original/v900.c gpsbabel-1.3.6.v900_2/v900.c
--- gpsbabel-1.3.6.original/v900.c    1970-01-01 02:00:00.000000000 +0200
+++ gpsbabel-1.3.6.v900_2/v900.c    2009-04-10 20:44:58.000000000 +0300
@@ -0,0 +1,367 @@
+/*
+    Support for Columbus/Visiontac V900 csv format
+        This format pads fields with NULL up to a fixed per field length.
+        Because of that, and because xcsv does not allows a regex as
a field delimiter,
+        a special c module is required.
+
+    Copyright (C) 2009 Tal Benavidor
+
+    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 USA
+
+    TODO:
+        - support way points
+        - QUESTION: course = heading ??
+                - HEIGHT: Altitude in meters (not corrected to WGS84...) ??
+                - indicate in ff_vecs_t that we do NOT support
reading of routes
+
+ */
+
+/******************************************************************************
+ FILE FORMAT INFO
+=================
+
+field          [start..stop]
+---------------------------------------------
+INDEX          0..5
+TAG           7
+DATE          9..14
+TIME          16..21
+LATITUDE N/S  23..32
+LONGITUDE E/W 34..44
+HEIGHT          46..50
+SPEED         52..55
+HEADING       57..59
+VOX           61..69 // BASIC MODE ONLY!!
+FIX_MODE      61..62 // ADVANCED MODE ONLY!!
+VALID         64..67 // ADVANCED MODE ONLY!!
+PDOP          69..73 // ADVANCED MODE ONLY!!
+HDOP          75..79 // ADVANCED MODE ONLY!!
+VDOP          81..85 // ADVANCED MODE ONLY!!
+VOX           87..95 // ADVANCED MODE ONLY!!
+
+The following two examples show "*" where null appears.
+
+------basic mode - start-------------------------
+INDEX,TAG,DATE,TIME,LATITUDE N/S,LONGITUDE E/W,HEIGHT,SPEED,HEADING,VOX
+1*****,T,090404,063401,31.765931N,035.206969E,821**,0***,0**,*********
+2*****,T,090404,063402,31.765931N,035.206969E,821**,0***,0**,*********
+3*****,T,090404,063403,31.765933N,035.206971E,821**,0***,0**,*********
+4*****,T,090404,063404,31.765933N,035.206971E,822**,0***,0**,*********
+5*****,T,090404,063407,31.765934N,035.206971E,824**,0***,0**,*********
+------basic mode - end---------------------------
+
+
+------advanced mode - start-------------------------
+INDEX,TAG,DATE,TIME,LATITUDE N/S,LONGITUDE
E/W,HEIGHT,SPEED,HEADING,FIX MODE,VALID,PDOP,HDOP,VDOP,VOX
+1*****,T,090204,055722,31.768380N,035.209656E,149**,0***,0**,3D,SPS
,2.6**,2.4**,1.0**,*********
+2*****,T,090204,055723,31.768380N,035.209656E,149**,0***,0**,3D,SPS
,2.5**,2.3**,0.9**,*********
+3*****,T,090204,055724,31.768378N,035.209658E,149**,0***,0**,3D,SPS
,2.5**,2.3**,0.9**,*********
+4*****,T,090204,055725,31.768378N,035.209658E,149**,0***,0**,3D,SPS
,2.5**,2.3**,0.9**,*********
+5*****,T,090204,055728,31.768376N,035.209660E,150**,0***,0**,3D,SPS
,2.5**,2.3**,0.9**,*********
+6*****,T,090204,055729,31.768376N,035.209660E,150**,0***,0**,3D,SPS
,4.0**,2.8**,2.9**,*********
+7*****,T,090204,055730,31.768376N,035.209661E,150**,0***,0**,3D,SPS
,2.5**,2.3**,0.9**,*********
+8*****,T,090204,055731,31.768376N,035.209661E,150**,0***,0**,3D,SPS
,2.5**,2.3**,0.9**,*********
+9*****,T,090204,055737,31.768326N,035.209993E,150**,0***,0**,3D,SPS
,2.5**,2.3**,0.9**,*********
+10****,T,090204,055738,31.768339N,035.209976E,153**,0***,0**,3D,SPS
,2.5**,2.3**,0.9**,*********
+11****,T,090204,055739,31.768338N,035.209991E,155**,0***,0**,3D,SPS
,2.5**,2.3**,0.9**,*********
+------advanced mode - end---------------------------
+
+
+
+some more info from   http://www.geosetter.de/mantis/view.php?id=609
+--------------------------------------------------------------------
+The advanced logging mode file format has the following header line
in the CVS file:
+
+INDEX,TAG,DATE,TIME,LATITUDE N/S,LONGITUDE
E/W,HEIGHT,SPEED,HEADING,FIX MODE,VALID,PDOP,HDOP,VDOP,VOX
+
+INDEX: Log number
+TAG: Tag type (can be ignored for geotagging use)
+DATE
+TIME
+LATITUDE N/S
+LONGITUDE E/W
+HEIGHT: Altitude in meters (not corrected to WGS84, maybe this can be
included in Geosetter?)
+SPEED: Speed in km/h
+HEADING: heading in degrees
+FIX MODE: 2D, 3D fix
+VALID: SPS or DGPS
+PDOP
+HDOP
+VDOP
+VOX: voicetag recorded
+
+===============================================================
+The standard mode logging file has the following tags:
+
+
+INDEX,TAG,DATE,TIME,LATITUDE N/S,LONGITUDE E/W,HEIGHT,SPEED,HEADING,VOX
+
+INDEX: Log number
+TAG: Tag type (can be ignored for geotagging use)
+DATE
+TIME
+LATITUDE N/S
+LONGITUDE E/W
+HEIGHT: Altitude in meters (not corrected to WGS84, maybe this can be
included in Geosetter?)
+SPEED: Speed in km/h
+HEADING: heading in degrees
+VOX: voicetag recorded
+
+******************************************************************************/
+
+#include "defs.h"
+#include <stdio.h>
+
+static FILE* fin = NULL;
+
+/* copied from dg-100.cpp */
+static void
+v900_log(const char *fmt, ...)
+{
+    va_list ap;
+    va_start (ap, fmt);
+
+    if (global_opts.debug_level < 1) {
+        return;
+    }
+    vfprintf(stderr, fmt, ap);
+    va_end(ap);
+}
+
+static void
+v900_rd_init(const char *fname)
+{
+    v900_log("%s(%s)\n",__func__,fname);
+    fin = fopen(fname,"rt");
+        if (!fin)
+        fatal("v900: could not open '%s'.\n", fname);
+}
+
+static void
+v900_rd_deinit(void)
+{
+    v900_log("%s\n",__func__);
+    if (fin)
+        fclose(fin);
+}
+
+/* read an entire line (everything including the last '\n').
+   return how much bytes were read.
+   this is a replacement for fgets(), because we deal with strings
+   containing nulls, and want to know how much bytes we actually read */
+int read_line(char *buf, int bufsize, FILE* fp)
+{
+    int bytes_read = 0;
+    buf[0] = 0;
+    while(1)
+    {
+        int c = fgetc(fp);
+        if (c != EOF)
+        {
+            if (bytes_read > bufsize-2)
+                fatal("read_line(): buf is already full and an
end-of-line marker was not found. bufsize=%d.\n", bufsize);
+            buf[bytes_read++] = c;
+            if (c=='\n')
+            {
+                buf[bytes_read] = 0;
+                return bytes_read;
+            }
+        }
+        else
+        {
+            return bytes_read;
+        }
+    }
+}
+
+#define INDEX_START    0
+#define TAG_START    7
+#define DATE_START    9
+#define TIME_START    16
+#define LATITUDE_START    23
+#define LONGITUDE_START    34
+#define HEIGHT_START    46
+#define SPEED_START    52
+#define HEADING_START    57
+#define VOX_START_BAS    61   /* BASIC MODE ONLY */
+
+#define FIX_MODE_START    61   /* ADVANCED MODE ONLY */
+#define VALID_START    64   /* ADVANCED MODE ONLY */
+#define PDOP_START    69   /* ADVANCED MODE ONLY */
+#define HDOP_START    75   /* ADVANCED MODE ONLY */
+#define VDOP_START    81   /* ADVANCED MODE ONLY */
+#define VOX_START_ADV    87   /* ADVANCED MODE ONLY */
+
+
+/* copied from dg-100.c - slight (incompatible) modification to how
the date parameter is used */
+static time_t
+bintime2utc(int date, int time)
+{
+    struct tm gpstime;
+
+    gpstime.tm_sec   = time % 100;
+    time /= 100;
+    gpstime.tm_min   = time % 100;
+    time /= 100;
+    gpstime.tm_hour  = time;
+
+    /*
+     * GPS year: 2000+; struct tm year: 1900+
+     * GPS month: 1-12, struct tm month: 0-11
+     */
+    gpstime.tm_mday  = date % 100;
+    date /= 100;
+    gpstime.tm_mon   = date % 100 - 1;
+    date /= 100;
+    gpstime.tm_year  = date + 100;
+
+    return(mkgmtime(&gpstime));
+}
+
+static void
+v900_read(void)
+{
+    char line[4096];
+    int is_advanced_mode = 0;
+    route_head *track;
+
+    v900_log("%s\n",__func__);
+
+/*
+Basic mode:    INDEX,TAG,DATE,TIME,LATITUDE N/S,LONGITUDE
E/W,HEIGHT,SPEED,HEADING,VOX
+Advanced mode: INDEX,TAG,DATE,TIME,LATITUDE N/S,LONGITUDE
E/W,HEIGHT,SPEED,HEADING,FIX MODE,VALID,PDOP,HDOP,VDOP,VOX
+*/
+    /* first, determine if this is advanced mode by reading the first
line (which does not contain nulls) */
+    if (!fgets(line, sizeof(line), fin))
+        fatal("v900: error reading header (first) line from input file\n");
+    is_advanced_mode = (NULL != strstr(line,"PDOP"));
+
+    v900_log("header line: %s",line);
+    v900_log("is_advance_mode=%d\n",is_advanced_mode);
+
+    track = route_head_alloc();
+    track->rte_name = xstrdup("V900 tracklog");
+    track->rte_desc = xstrdup("V900 GPS tracklog data");
+    track_add_head(track);
+
+    while (1)
+    {
+        waypoint *wpt;
+        char c;
+
+        int len = read_line(line, sizeof(line), fin);
+        if (len == 0)
+            break;        /* EOF */
+
+        /* replace the last '\n' with null */
+        if (len > 0 && line[len-1] == '\n')
+            line[len-1] = 0;  /* error if not reached here! */
+
+        /* change all "," characters to NULLs.
+                   so every field is null terminated.
+                 */
+        line[TAG_START-1] = 0;
+        line[DATE_START-1] = 0;
+        line[TIME_START-1] = 0;
+        line[LATITUDE_START-1] = 0;
+        line[LONGITUDE_START-1] = 0;
+        line[HEIGHT_START-1] = 0;
+        line[SPEED_START-1] = 0;
+        line[HEADING_START-1] = 0;
+        if(is_advanced_mode)
+        {
+            /* change all "," characters to NULLs.
+                   so every field is null terminated.
+                 */
+            line[FIX_MODE_START-1] = 0;
+            line[VALID_START-1] = 0;
+            line[PDOP_START-1] = 0;
+            line[HDOP_START-1] = 0;
+            line[VDOP_START-1] = 0;
+            line[VOX_START_ADV-1] = 0;
+        }
+        else
+        {
+            line[VOX_START_BAS-1] = 0;
+        }
+
+        wpt = waypt_new();
+
+        /* lat is a string in the form: 31.768380N */
+        c = line[LATITUDE_START+9];    /* N/S */
+        wpt->latitude = atof(line+LATITUDE_START);
+        if (c == 'S')
+            wpt->latitude = -wpt->latitude;
+
+        /* lon is a string in the form: 035.209656E */
+        c = line[LONGITUDE_START+10]; /* get E/W */
+        line[LONGITUDE_START+10] = 0; /* the E will confuse atof(),
if not removed */
+        wpt->longitude = atof(line+LONGITUDE_START);
+        if (c == 'W')
+            wpt->longitude = -wpt->longitude;
+
+        wpt->altitude = atoi(line+HEIGHT_START);
+
+        /* handle date/time fields */
+        {
+          int date, time;
+          date = atoi(line+DATE_START);
+          time = atoi(line+TIME_START);
+          wpt->creation_time = bintime2utc(date, time);
+        }
+
+        wpt->speed = KPH_TO_MPS(atoi(line+SPEED_START));
+        wpt->wpt_flags.speed = 1;
+
+        wpt->course = atoi(line+HEADING_START);
+        wpt->wpt_flags.course = 1;
+
+        if(is_advanced_mode)
+        {
+            wpt->hdop = atof(line+HDOP_START);
+            wpt->vdop = atof(line+VDOP_START);
+            wpt->pdop = atof(line+PDOP_START);
+
+            /* handle fix mode (2d, 3d, etc.) */
+            if (!strcmp(line+VALID_START,"DGPS"))
+                wpt->fix = fix_dgps;
+            else if (!strcmp(line+FIX_MODE_START,"3D"))
+                wpt->fix = fix_3d;
+            else if (!strcmp(line+FIX_MODE_START,"2D"))
+                wpt->fix = fix_2d;
+            else
+                /* possible values:
fix_unknown,fix_none,fix_2d,fix_3d,fix_dgps,fix_pps */
+                wpt->fix = fix_unknown;
+        }
+
+        track_add_wpt(track, wpt);
+    }
+}
+
+ff_vecs_t v900_vecs = {
+    ff_type_file,
+    {ff_cap_read, ff_cap_read, ff_cap_none}, /* Read only format. May
only read trackpoints and waypoints. */
+    v900_rd_init,
+    NULL,          /* wr_init */
+    v900_rd_deinit,
+    NULL,          /* wr_deinit */
+    v900_read,
+    NULL,          /* write */
+    NULL,
+    NULL,          /* args */
+    CET_CHARSET_UTF8, 1,    /* Could be  US-ASCII, since we only read
"0-9,A-Z\n\r" */
+    {NULL,NULL,NULL,NULL,NULL,NULL}
+};
+
diff -Nurp gpsbabel-1.3.6.original/vecs.c gpsbabel-1.3.6.v900_2/vecs.c
--- gpsbabel-1.3.6.original/vecs.c    2008-10-31 00:40:04.000000000 +0200
+++ gpsbabel-1.3.6.v900_2/vecs.c    2009-04-10 20:45:12.000000000 +0300
@@ -153,6 +153,7 @@ extern ff_vecs_t jtr_vecs;
 extern ff_vecs_t sbp_vecs;
 extern ff_vecs_t mmo_vecs;
 extern ff_vecs_t skyforce_vecs;
+extern ff_vecs_t v900_vecs;

 static
 vecs_t vec_list[] = {
@@ -876,6 +877,12 @@ vecs_t vec_list[] = {
             "Skymap / KMD150 ascii files",
             NULL
         },
+        {
+            &v900_vecs,
+            "v900",
+            "Columbus/Visiontac V900 files (.csv)",
+            NULL
+        },


 #endif // MAXIMAL_ENABLED

------------------------------------------------------------------------------
This SF.net email is sponsored by:
High Quality Requirements in a Collaborative Environment.
Download a free trial of Rational Requirements Composer Now!
http://p.sf.net/sfu/www-ibm-com
_______________________________________________
Gpsbabel-code mailing list  http://www.gpsbabel.org
Gpsbabel-code@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/gpsbabel-code