示例#1
0
        // send, wait for response and return received packet:
        public MPacketReceived Transact(MPacket packet)
        {
            string          str      = packet.ToString();
            MPacketReceived packetIn = new MPacketReceived();

            m_physLayer.Transact(str, packetIn);
            return(packetIn);
        }
示例#2
0
        // this is a "class packet" factory which converts received packets into usable classes
        // (packet classes defined in MagellanProtoDef.cs). We assume that basicParse() was run
        // on this packet before calling fromString()
        public MPacket fromString()
        {
            MPacket ret = null;

            if (m_string == null)
            {
                logError("MPacketReceived:fromString() -- m_string==null");
                return(ret);
            }

            switch (m_header)
            {
            case "PMGNVER":
                ret = this;                             // all we need is already in fields array
                break;

            case "PMGNRTE":
            // $PMGNRTE,14,2,c,1,T01P03,a,T01P04,a*35
            case "PMGNTRK":
            // $PMGNTRK,3334.530,N,11739.837,W,00000,M,034414.24,A*62
            case "PMGNWPL":
                // $PMGNWPL,3328.069,N,11738.812,W,0000000,M,Road to,GCF320 = Road to Wat,a*68
                ret = this;                             // all we need is already in fields array
                break;

            case "PMGNST":
            case "GPGSV":
            case "GPGGA":
            case "GPRMC":
            case "GPGLL":
                ret = this;                             // all we need is already in fields array
                break;

            default:
                logError("MPacketReceived:fromString() -- unknown header=" + m_header);
                ret = this;                             // may be all we need is already in fields array
                break;
            }

            return(ret);
        }
示例#3
0
        public void StartRealTime(GpsRealTimeHandler realtimeCallback)
        {
            int  total     = 0;
            int  maxErrors = 5;
            int  errors    = maxErrors;
            bool finished  = false;

            m_stopRealTime = false;

            while (!finished && !m_stopRealTime)
            {
                GpsRealTimeData pvtData = new GpsRealTimeData();                                // will be returned empty if no data

                MPacketReceived received = null;
                try
                {
                    received = m_linkLayer.ReceivePacket();
                    if (!received.isGood)
                    {
                        m_linkLayer.logError("StartRealTime: bad packet received, count=" + total);
                        pvtData.comment = "bad data packet from GPS";
                        realtimeCallback(pvtData);
                        continue;
                    }
                }
                catch (Exception e)
                {
                    m_linkLayer.logError("StartRealTime: " + e.Message + "  count=" + total);
                    //if(received != null)
                    {
                        try
                        {
                            m_linkLayer.ReOpen();
                        }
                        catch (Exception ee)
                        {
                            m_linkLayer.logError("while ReOpen(): " + ee.Message);
                        }
                    }
                    pvtData.comment = e.Message.StartsWith("Timeout") ?
                                      "GPS not responding - check cable" : ("error: " + e.Message);
                    realtimeCallback(pvtData);
                    continue;
                }
                //m_linkLayer.log("" + total + " ===  " + received);
                m_linkLayer.log("StartRealTime: good packet received, count=" + total + "   " + received);
                if (received.header.EndsWith("GGA"))                    // NMEA GGA expected for location
                {
                    m_linkLayer.log("StartRealTime: " + received.header + " packet received, count=" + total + "   content=" + received);
                    try
                    {
                        MPacket pvt = received.fromString();

                        /*
                         *      $GPGGA,123519,4807.038,N,01131.000,E,1,08,0.9,545.4,M,46.9,M,,*47
                         *
                         *      Where:
                         *              GGA          Global Positioning System Fix Data
                         *      0	123519       Fix taken at 12:35:19 UTC
                         *      1	4807.038,N   Latitude 48 deg 07.038' N
                         *      3	01131.000,E  Longitude 11 deg 31.000' E
                         *      5	1            Fix quality: 0 = invalid
                         *                                                              1 = GPS fix
                         *                                                              2 = DGPS fix
                         *                                                              6 = estimated (2.3 feature)
                         *      6	08           Number of satellites being tracked
                         *      7	0.9          Horizontal dilution of position
                         *      8	545.4,M      Altitude, Meters, above mean sea level
                         *      10	46.9,M       Height of geoid (mean sea level) above WGS84
                         *                                              ellipsoid
                         *      12	(empty field) time in seconds since last DGPS update
                         *      13	(empty field) DGPS station ID number
                         * 47          the checksum data, always begins with *
                         */

                        double Lat  = pvt.parseLat(1);
                        double Lng  = pvt.parseLng(1);
                        double Elev = pvt.parseElev(8);                                 // alt above mean sea level
                        pvtData.location = new GeoCoord(Lng, Lat, Elev);
                        //m_linkLayer.log("coord=" + pvtData.location);

                        // time component:
                        pvtData.time = pvt.parseNmeaTime(0, Project.localToZulu(DateTime.Now));                         // UTC

                        // errors and velocity:
                        pvtData.posError  = 0;
                        pvtData.posErrorH = 0;
                        pvtData.posErrorV = 0;
                        pvtData.fix       = 0;                                          // failed integrity check
                        switch ((string)pvt.fields[5])
                        {
                        case "0":                                                       // invalid
                            pvtData.fix = 1;                                            // invalid
                            break;

                        case "1":                                                       // GPS fix
                            pvtData.fix = 2;                                            // two dimensional
                            break;

                        case "2":                                                       // DGPS fix
                            pvtData.fix = 4;                                            // two dimensional differential
                            break;

                        case "6":                                                       // estimated
                            pvtData.fix = 6;                                            // estimated
                            break;
                        }
                        pvtData.velocityEast  = 0;
                        pvtData.velocityNorth = 0;
                        pvtData.velocityUp    = 0;

                        pvtData.comment = "received " + received.header;
                        //realtimeCallback(pvtData);

                        total++;
                        errors = maxErrors;
                    }
                    catch (Exception ee)
                    {
                        m_linkLayer.logError("StartRealTime: " + ee.Message);
                    }
                }
                else if (received.header.EndsWith("RMC"))                       // NMEA RMC may come
                {
                    m_linkLayer.log("StartRealTime: " + received.header + " packet received, count=" + total + "   content=" + received);
                    try
                    {
                        MPacket pvt = received.fromString();

                        // $GPRMC,052458.73,V,3334.6441,N,11739.6622,W,00.0,000.0,290103,13,E*4F

                        /*
                         * see http://www.gpsinformation.org/dale/nmea.htm for NMEA reference
                         *
                         * RMC - NMEA has its own version of essential gps pvt (position, velocity, time) data.
                         * It is called RMC, The Recommended Minimum, which might look like:
                         *
                         * $GPRMC,123519,A,4807.038,N,01131.000,E,022.4,084.4,230394,003.1,W*6A
                         * $GPRMC,050821.000,A,3334.5551,N,11739.7705,W,0.00,,251006,,,A*67
                         *
                         * Where:
                         *  RMC          Recommended Minimum sentence C
                         * 0	123519       Fix taken at 12:35:19 UTC
                         * 1	A            Status A=active or V=Void.
                         * 2	4807.038,N   Latitude 48 deg 07.038' N
                         * 4	01131.000,E  Longitude 11 deg 31.000' E
                         * 6	022.4        Speed over the ground in knots
                         * 7	084.4        Track angle in degrees True
                         * 8	230394       Date - 23rd of March 1994
                         * 9	003.1,W      Magnetic Variation
                         * 6A          The checksum data, always begins with *
                         *
                         * Note that, as of the 2.3 release of NMEA, there is a new field in the RMC sentence
                         * at the end just prior to the checksum. The value of the entry is
                         * A=autonomous, D=differential, E=estimated, N=Data not valid.
                         */
                        bool status = "A".Equals(pvt.fields[1]);
                        if (status)
                        {
                            double Lat  = pvt.parseLat(2);
                            double Lng  = pvt.parseLng(2);
                            double Elev = 0.0d;
                            pvtData.location = new GeoCoord(Lng, Lat, Elev);
                            //m_linkLayer.log("coord=" + pvtData.location);

                            // time component (only time part):
                            pvtData.time = pvt.parseNmeaDateTime(0, 8); // UTC

                            if (!"".Equals(pvt.fields[6]))
                            {
                                double knots = Convert.ToDouble(pvt.fields[6]);
                                pvtData.velocity = knots * Distance.METERS_PER_NAUTICAL_MILE / 3600.0d;
                                // calculate velocity vector based on track angle:
                                if (!"".Equals(pvt.fields[7]))
                                {
                                    double trackAngleRad = Convert.ToDouble(pvt.fields[7]) * Math.PI / 180.0d;
                                    pvtData.velocityNorth = pvtData.velocity * Math.Cos(trackAngleRad);
                                    pvtData.velocityEast  = pvtData.velocity * Math.Sin(trackAngleRad);
                                }
                            }

                            pvtData.fix     = 2;                                                // assume two-dimensional
                            pvtData.comment = "received " + received.header;
                            realtimeCallback(pvtData);
                        }
                        total++;
                        errors = maxErrors;
                    }
                    catch (Exception ee)
                    {
                        m_linkLayer.logError("StartRealTime: " + ee.Message);
                    }
                }
                else if (received.header.EndsWith("GLL"))                       // NMEA GLL may come
                {
                    m_linkLayer.log("StartRealTime: GLL packet received, count=" + total + "   content=" + received);
                    try
                    {
                        MPacket pvt = received.fromString();
                        // $GPGLL,3334.6464,N,11739.6583,W,052707.129,A*29

                        /*
                         * see http://www.gpsinformation.org/dale/nmea.htm for NMEA reference
                         *
                         * GLL - Geographic Latitude and Longitude is a holdover from Loran data and some old units
                         *   may not send the time and data valid information if they are emulating Loran data.
                         *   If a gps is emulating Loran data they may use the LC Loran prefix instead of GP.
                         *
                         * $GPGLL,4916.45,N,12311.12,W,225444,A,*31
                         *
                         * Where:
                         *  GLL          Geographic position, Latitude and Longitude
                         * 0	4916.46,N    Latitude 49 deg. 16.45 min. North
                         * 2	12311.12,W   Longitude 123 deg. 11.12 min. West
                         * 4	225444       Fix taken at 22:54:44 UTC
                         * 5	A            Data valid or V (void)
                         * 31          checksum data
                         *
                         */
                        bool status = "A".Equals(pvt.fields[5]);
                        if (status)
                        {
                            double Lat  = pvt.parseLat(0);
                            double Lng  = pvt.parseLng(0);
                            double Elev = 0.0d;
                            pvtData.location = new GeoCoord(Lng, Lat, Elev);
                            //m_linkLayer.log("coord=" + pvtData.location);

                            // time component (only time part):
                            pvtData.time = pvt.parseNmeaTime(4, Project.localToZulu(DateTime.Now)); // UTC

                            pvtData.fix     = 2;                                                    // assume two-dimensional
                            pvtData.comment = "received " + received.header;
                            //realtimeCallback(pvtData);
                        }
                        total++;
                        errors = maxErrors;
                    }
                    catch (Exception ee)
                    {
                        m_linkLayer.logError("StartRealTime: " + ee.Message);
                    }
                }
                else if (received.header.EndsWith("GSV"))                       // NMEA GSV may come for satellite reception status
                {
                    m_linkLayer.log("StartRealTime: GSV packet received, count=" + total + "   content=" + received);

                    /*
                     * see http://www.gpsinformation.org/dale/nmea.htm for NMEA reference
                     *
                     * $GPGSV,3,1,08,14,69,204,,15,57,105,36,18,45,047,36,03,42,263,36*71
                     * $GPGSV,2,1,08,01,40,083,46,02,17,308,41,12,07,344,39,14,22,228,45*75
                     *
                     * Where:
                     *  GSV          Satellites in view
                     * 0	2            Number of sentences for full data
                     * 1	1            sentence 1 of 2
                     * 2	08           Number of satellites in view
                     * for up to 4 satellites per sentence {
                     *      3	01           Satellite PRN number
                     *      4	40           Elevation, degrees
                     *      5	083          Azimuth, degrees
                     *      6	46           Signal strength - higher is better
                     * }
                     * 75          the checksum data, always begins with *
                     */

                    //MPacket pvt  = received.fromString();
                    //pvtData.comment = "received";
                    //realtimeCallback(pvtData);

                    total++;
                    errors = maxErrors;
                }
                else if (received.header.EndsWith("VTG"))                       // NMEA GSA may come
                {
                    m_linkLayer.log("StartRealTime: GPVTG packet received, count=" + total + "   content=" + received);
                    // $GPVTG,309.62,T,,M,0.13,N,0.2,K*6E

                    /*
                     *  VTG - Course Over Ground and Ground Speed
                     *
                     *      Name		Example		Units	Description
                     *      Message ID	$GPVTG				VTG protocol header
                     *      Course		309.62		degrees Measured heading
                     *      Reference	T					True
                     *      Course					degrees	Measured heading
                     *      Reference	M					Magnetic
                     *      Speed		0.13		knots	Measured horizontal speed
                     *      Units		N			Knots
                     *      Speed		0.2			Km/hr	Measured horizontal speed
                     *      Units		K					Kilometers per hour
                     */
                }
                else if (received.header.EndsWith("GSA"))                       // NMEA GSA may come
                {
                    m_linkLayer.log("StartRealTime: GPGSA packet received, count=" + total + "   content=" + received);
                    // $GPGSA,A,2,15,18,14,31,,,,,,,,,05.6,05.6,*17

                    /*
                     * see http://www.gpsinformation.org/dale/nmea.htm for NMEA reference
                     *
                     * GSA - GPS DOP and active satellites. This sentence provides details on the nature of the
                     * fix. It includes the numbers of the satellites being used in the current solution and
                     * the DOP. DOP (dilution of precision) is an indication of the effect of satellite geometry
                     * on the accuracy of the fix. It is a unitless number where smaller is better. For 3D fixes
                     * using 4 satellites a 1.0 would be considered to be a perfect number. For overdetermined
                     * solutions it is possible to see numbers below 1.0. There are differences in the way the
                     * PRN's are presented which can effect the ability of some programs to display this data.
                     * For example, in the example shown below there are 5 satellites in the solution and
                     * the null fields are scattered indicating that the almanac would show satellites in
                     * the null positions that are not being used as part of this solution. Other receivers
                     * might output all of the satellites used at the beginning of the sentence with the
                     * null field all stacked up at the end. This difference accounts for some satellite
                     * display programs not always being able to display the satellites being tracked.
                     *
                     * $GPGSA,A,3,04,05,,09,12,,,24,,,,,2.5,1.3,2.1*39
                     *
                     * Where:
                     *  GSA      Satellite status
                     *  A        Auto selection of 2D or 3D fix (M = manual)
                     *  3        3D fix - other values include: 1 = no fix
                     *                                          2 = 2D fix
                     *  04,05... PRNs of satellites used for fix (space for 12)
                     *  2.5      PDOP (dilution of precision)
                     *  1.3      Horizontal dilution of precision (HDOP)
                     *  2.1      Vertical dilution of precision (VDOP)
                     * 39      the checksum data, always begins with *
                     *
                     */
                }
                else
                {
                    m_linkLayer.log("StartRealTime: good other (unrecognized) packet received, count=" + total + "   content=" + received);
                }
            }             // end while()

            m_linkLayer.log("StartRealTime: finished receiving fixes count=" + total);
        }
 // send, wait for response and return received packet:
 public MPacketReceived Transact(MPacket packet)
 {
     string str = packet.ToString();
     MPacketReceived packetIn = new MPacketReceived();
     m_physLayer.Transact(str, packetIn);
     return packetIn;
 }
 public void SendPacket(MPacket packet)
 {
     string str = packet.ToString();		// also makes sure all fields are clean of wrong symbols like ","
     m_physLayer.Send(str);
 }
示例#6
0
        public void SendPacket(MPacket packet)
        {
            string str = packet.ToString();

            m_physLayer.Send(str);
        }
 public void SendPacket(MPacket packet)
 {
     string str = packet.ToString();
     m_physLayer.Send(str);
 }
        public void PutWaypoints(ArrayList waypoints, GpsProgressHandler progressCallback)
        {
            int count = 0;
            int toSend = waypoints.Count;
            int maxErrors = 5;
            int errors = maxErrors;
            int toTrim = 40;

            //m_linkLayer.SetHandshake(Project.gpsMagellanHandshake);
            m_linkLayer.SetHandshake(true);		// safer with handshake on
            m_linkLayer.SetTransferMode(true);

            foreach(Waypoint wpt in waypoints)
            {
                // send toSend MPacket's, followed by PMGNCMD
                try
                {
                    MPacket packetToSend = new MPacket("PMGNWPL");

                    // $PMGNWPL,3339.889,N,11736.283,W,0000155,M,WPT001,this is comment,a*7E

                    packetToSend.packCoord(wpt.Location);	// adds 6 fields to array

                    //string name = wpt.WptName;
                    string name = puttingRoute ? (wpt.WptName.Length > 0 ? wpt.WptName : wpt.Name) : wpt.WptName;
                    string desc = wpt.Desc.Length > 0 ? wpt.Desc : wpt.UrlName;

                    if(!puttingRoute)
                    {
                        // keep it in sync with GarminProtoLinkProtocols:sendWaypoint()
                        if(Project.gpsWptDescrAsName)
                        {
                            string _desc = desc;
                            if(wpt.LiveObjectType == LiveObjectTypes.LiveObjectTypeGeocache && name.StartsWith("GC"))
                            {
                                desc = name + " = " + desc;
                            }
                            if(_desc.Length > 0)
                            {
                                name = _desc;
                            }
                        }
                        // end sync

                        name = name.Length > 12 ? name.Substring(0, 12) : name;
                    }

                    desc = desc.Length > toTrim ? desc.Substring(0, toTrim) : desc;

                    packetToSend.fields.Add(name);			// name - truncated in GPS
                    packetToSend.fields.Add(desc);			// comment has more characters in GPS
                    string icon = wpt.Found ? "b" : "a";
                    packetToSend.fields.Add(icon);			// icon - "crossed box"=a  or "box in the box"=b

                    // link layer will make sure all fields are clean of wrong symbols like ","
                    m_linkLayer.SendPacket(packetToSend);
                    count++;
                    if(count % 10 == 0)
                    {
                        progressCallback("IP: downloading to GPS - waypoint ", count, toSend);
                    }
                }
                catch (Exception e)
                {
                    m_linkLayer.logError("PutWaypoints: " + e.Message + "  count=" + count);
                    if(errors-- > 0)
                    {
                        // on timeout, try continue sending and bail out after too many failures
                        continue;
                    }
                    else
                    {
                        m_linkLayer.logError("PutWaypoints: too many errors, stopping transfer");
                        throw(e);
                    }
                }
            }
            m_linkLayer.SendPacket(new MPacketCmd("END"));

            if(!puttingRoute)
            {
                m_linkLayer.SetTransferMode(false);
            }

            progressCallback("OK: downloaded to GPS - waypoints", count, toSend);

            m_linkLayer.log("OK: downloaded to GPS - waypoints: " + count);
        }
        public void PutRoutes(ArrayList routes, GpsProgressHandler progressCallback, int startRouteNumber)
        {
            // here is a problem: the SporTrack will reject routes which have same waypoint repeating twice on one leg.
            // the waypoint can repeat in the route many times, if separated by other waypoints.
            // rejection happens in the form of "UNABLE" response on the physical layer, m_linkLayer.ErrorCount() shows that.
            // the condition should not happen, as it is cleared during creation of the routes in LayerWaypoints.cs

            // we need to send all waypoints for all routes first, and then send linking info.
            m_linkLayer.resetErrorCount();

            // make list of relevant waypoints and count them
            ArrayList trkptsToSend = new ArrayList();
            int toSendWpt = 0;		// for ProgressCallback
            int toSendPkt = 0;
            int routeNumber = startRouteNumber;	// 1 to 20
            foreach(Track route in routes)
            {
                if(route.isRoute)
                {
                    int cnt = 0;
                    Waypoint prevWpt = null;
                    for(int i=0; i < route.Trackpoints.Count ;i++)
                    {
                        Waypoint trkpt = (Waypoint)route.Trackpoints.GetByIndex(i);
                        if(prevWpt == null || !prevWpt.Location.almostAs(trkpt.Location, 0.0002))	// 0.0001 degree = 10 meters
                        {
                            Waypoint cloneTrkpt = new Waypoint(trkpt);
                            string trkptName = toTptName(routeNumber, trkpt.Name);		// use .Name here, as WptName is empty for rtept's
                            cloneTrkpt.WptName = truncateName(trkptName);
                            cloneTrkpt.Desc = trkptName;
                            trkptsToSend.Add(cloneTrkpt);
                            prevWpt = trkpt;
                            cnt++;
                        }
                    }
                    toSendPkt += (cnt + 1) / 2;
                    toSendWpt += cnt;
                    routeNumber++;
                }
            }
            if(toSendWpt == 0)
            {
                progressCallback("Error: no routes to upload ", 0, 0);
                return;
            }

            puttingRoute = true;
            PutWaypoints(trkptsToSend, progressCallback);		// will leave TransferMode
            puttingRoute = false;

            int count = 0;
            int maxErrors = 5;
            int errors = maxErrors;
            int maxRoutepointCount = 0;
            string maxRoutepointName = "";

            routeNumber = startRouteNumber;
            foreach(Track route in routes)
            {
                if(route.isRoute)
                {
                    // make a temp list of trackpoints - specifically for this route, and count them:
                    ArrayList trackpoints = new ArrayList();
                    foreach(Waypoint wpt in trkptsToSend)
                    {
                        if(wpt.TrackId == route.Id)
                        {
                            trackpoints.Add(wpt);
                        }
                    }
                    int toSendThisRoute = (trackpoints.Count + 1) / 2;
                    if(trackpoints.Count > maxRoutepointCount)
                    {
                        maxRoutepointCount = trackpoints.Count;
                        maxRoutepointName = route.Name;
                    }

                    int countThisRoute = 1;
                    for(int i=0; i < trackpoints.Count ;i+=2)
                    {
                        int numPoints = (trackpoints.Count - i > 1) ? 2 : 1;
                        Waypoint trkpt1 = (Waypoint)trackpoints[i];
                        string trkptName1 = trkpt1.WptName.Trim();
                        Waypoint trkpt2 = numPoints > 1 ? (Waypoint)trackpoints[i + 1] : null;
                        string trkptName2 = numPoints > 1 ? trkpt2.WptName.Trim() : "";

                        // send MPackets, followed by PMGNCMD
                        try
                        {
                            MPacket packetToSend = new MPacket("PMGNRTE");

                            // $PMGNRTE,15,5,c,2,T02P09,a,T02P10,a*3F

                            packetToSend.fields.Add("" + toSendThisRoute);
                            packetToSend.fields.Add("" + countThisRoute);
                            packetToSend.fields.Add("c");
                            packetToSend.fields.Add("" + routeNumber);
                            packetToSend.fields.Add(trkptName1);
                            packetToSend.fields.Add("a");
                            if(numPoints > 1)
                            {
                                packetToSend.fields.Add(trkptName2);
                                packetToSend.fields.Add("a");
                            }

                            m_linkLayer.SendPacket(packetToSend);
                            countThisRoute++;
                            count++;
                            if(count % 10 == 0)
                            {
                                progressCallback("IP: downloading to GPS - route packet ", count, toSendPkt);
                            }
                        }
                        catch (Exception e)
                        {
                            m_linkLayer.logError("PutRoutes: " + e.Message + "  count=" + count);
                            if(errors-- > 0)
                            {
                                // on timeout, try continue sending and bail out after too many failures
                                continue;
                            }
                            else
                            {
                                m_linkLayer.logError("PutRoutes: too many errors, stopping transfer");
                                throw(e);
                            }
                        }
                    }
                    routeNumber++;
                }
            }

            m_linkLayer.SendPacket(new MPacketCmd("END"));
            m_linkLayer.SetTransferMode(false);

            if(m_linkLayer.ErrorCount() > 0)
            {
                // caught some packets with "UNABLE" response.
                progressCallback("Errors: " + m_linkLayer.ErrorCount() + " out of route packets: ", count, toSendPkt);
                Project.ErrorBox(Project.mainCommand.gpsManagerForm(), "Route '" + maxRoutepointName + "' (" + maxRoutepointCount
                    + " route points after combing) failed to load, possibly due to 30 legs-per-route limitation of the Magellan devices."
                    + "\n\nYou can break the route into smaller ones, or remove some mid-route points."
                    + "\nAlternatively you can try clearing waypoints/routes memory in the device.");
            }
            else
            {
                progressCallback("OK: downloaded to GPS - route packets", count, toSendPkt);
            }
            m_linkLayer.log("OK: downloaded to GPS - route packets: " + count + " errors: " + m_linkLayer.ErrorCount());
        }
        public void SendPacket(MPacket packet)
        {
            string str = packet.ToString();                     // also makes sure all fields are clean of wrong symbols like ","

            m_physLayer.Send(str);
        }