diff --git a/src/GPSStatus.h b/src/GPSStatus.h index 3d1e5a6c..6023a6db 100644 --- a/src/GPSStatus.h +++ b/src/GPSStatus.h @@ -19,28 +19,39 @@ class GPSStatus : public Status bool hasLock = false; // default to false, until we complete our first read bool isConnected = false; // Do we have a GPS we are talking to - int32_t latitude = 0, longitude = 0; // as an int mult by 1e-7 to get value as double - int32_t altitude = 0; - uint32_t dop = 0; // Diminution of position; PDOP where possible (UBlox), HDOP otherwise (TinyGPS) in 10^2 units (needs - // scaling before use) - uint32_t heading = 0; - uint32_t numSatellites = 0; + + Position p = Position_init_default; public: GPSStatus() { statusType = STATUS_TYPE_GPS; } + + // proposed for deprecation GPSStatus(bool hasLock, bool isConnected, int32_t latitude, int32_t longitude, int32_t altitude, uint32_t dop, uint32_t heading, uint32_t numSatellites) : Status() { this->hasLock = hasLock; this->isConnected = isConnected; - this->latitude = latitude; - this->longitude = longitude; - this->altitude = altitude; - this->dop = dop; - this->heading = heading; - this->numSatellites = numSatellites; + + this->p.latitude_i = latitude; + this->p.longitude_i = longitude; + this->p.altitude = altitude; + this->p.PDOP = dop; + this->p.ground_track = heading; + this->p.sats_in_view = numSatellites; } + + // preferred method + GPSStatus(bool hasLock, bool isConnected, Position pos) + : Status() + { + this->hasLock = hasLock; + this->isConnected = isConnected; + + // all-in-one struct copy + this->p = pos; + } + GPSStatus(const GPSStatus &); GPSStatus &operator=(const GPSStatus &); @@ -56,7 +67,7 @@ class GPSStatus : public Status NodeInfo *node = nodeDB.getNode(nodeDB.getNodeNum()); return node->position.latitude_i; } else { - return latitude; + return p.latitude_i; } } @@ -66,7 +77,7 @@ class GPSStatus : public Status NodeInfo *node = nodeDB.getNode(nodeDB.getNodeNum()); return node->position.longitude_i; } else { - return longitude; + return p.longitude_i; } } @@ -76,22 +87,27 @@ class GPSStatus : public Status NodeInfo *node = nodeDB.getNode(nodeDB.getNodeNum()); return node->position.altitude; } else { - return altitude; + return p.altitude; } } + uint32_t getDOP() const { return p.PDOP; } - uint32_t getDOP() const { return dop; } + uint32_t getHeading() const { return p.ground_track; } - uint32_t getHeading() const { return heading; } - - uint32_t getNumSatellites() const { return numSatellites; } + uint32_t getNumSatellites() const { return p.sats_in_view; } bool matches(const GPSStatus *newStatus) const { - return (newStatus->hasLock != hasLock || newStatus->isConnected != isConnected || newStatus->latitude != latitude || - newStatus->longitude != longitude || newStatus->altitude != altitude || newStatus->dop != dop || - newStatus->heading != heading || newStatus->numSatellites != numSatellites); + return (newStatus->hasLock != hasLock || + newStatus->isConnected != isConnected || + newStatus->p.latitude_i != p.latitude_i || + newStatus->p.longitude_i != p.longitude_i || + newStatus->p.altitude != p.altitude || + newStatus->p.altitude_hae != p.altitude_hae || + newStatus->p.PDOP != p.PDOP || + newStatus->p.ground_track != p.ground_track || + newStatus->p.sats_in_view != p.sats_in_view); } int updateStatus(const GPSStatus *newStatus) { @@ -102,17 +118,15 @@ class GPSStatus : public Status initialized = true; hasLock = newStatus->hasLock; isConnected = newStatus->isConnected; - latitude = newStatus->latitude; - longitude = newStatus->longitude; - altitude = newStatus->altitude; - dop = newStatus->dop; - heading = newStatus->heading; - numSatellites = newStatus->numSatellites; + + p = newStatus->p; } if (isDirty) { if (hasLock) - DEBUG_MSG("New GPS pos lat=%f, lon=%f, alt=%d, pdop=%f, heading=%f, sats=%d\n", latitude * 1e-7, longitude * 1e-7, - altitude, dop * 1e-2, heading * 1e-5, numSatellites); + DEBUG_MSG("New GPS pos lat=%f, lon=%f, alt=%d, pdop=%.2f, heading=%.2f, sats=%d\n", + p.latitude_i * 1e-7, p.longitude_i * 1e-7, + p.altitude, p.PDOP * 1e-2, p.ground_track * 1e-5, + p.sats_in_view); else DEBUG_MSG("No GPS lock\n"); onNewStatus.notifyObservers(this); diff --git a/src/gps/UBloxGPS.cpp b/src/gps/UBloxGPS.cpp index 21ed5af3..9f8285bb 100644 --- a/src/gps/UBloxGPS.cpp +++ b/src/gps/UBloxGPS.cpp @@ -170,28 +170,30 @@ bool UBloxGPS::lookForLocation() { bool foundLocation = false; - // catch fixType changes here, instead of whileActive() - if (ublox.moduleQueried.fixType) { - fixType = ublox.getFixType(); - } - - // check if GPS has an acceptable lock - if (! hasLock()) { - return false; - } - // check if a complete GPS solution set is available for reading // (some of these, like lat/lon are redundant and can be removed) - if ( ! (ublox.moduleQueried.latitude && + if ( ! (ublox.moduleQueried.fixType && + ublox.moduleQueried.latitude && ublox.moduleQueried.longitude && ublox.moduleQueried.altitude && ublox.moduleQueried.pDOP && - ublox.moduleQueried.gpsiTOW)) + ublox.moduleQueried.gpsDay)) { // Not ready? No problem! We'll try again later. return false; } + fixType = ublox.getFixType(); +#ifdef UBLOX_EXTRAVERBOSE + DEBUG_MSG("FixType=%d\n", fixType); +#endif + + // check if GPS has an acceptable lock + if (! hasLock()) { + ublox.flushPVT(); // reset ALL freshness flags + return false; + } + // read lat/lon/alt/dop data into temporary variables to avoid // overwriting global variables with potentially invalid data int32_t tmp_dop = ublox.getPDOP(0); // PDOP (an accuracy metric) is reported in 10^2 units so we have to scale down when we use it @@ -241,9 +243,13 @@ bool UBloxGPS::lookForLocation() pos_timestamp = tmp_ts; dop = tmp_dop; } else { - DEBUG_MSG("Invalid location discarded\n"); + // INVALID solution - should never happen + DEBUG_MSG("Invalid location lat/lon/hae/dop %d/%d/%d/%d - discarded\n", + tmp_lat, tmp_lon, tmp_alt_hae, tmp_dop); } + ublox.flushPVT(); // reset ALL freshness flags at the end + return foundLocation; } diff --git a/src/plugins/PositionPlugin.cpp b/src/plugins/PositionPlugin.cpp index 9dfe07d5..b772954c 100644 --- a/src/plugins/PositionPlugin.cpp +++ b/src/plugins/PositionPlugin.cpp @@ -38,7 +38,45 @@ MeshPacket *PositionPlugin::allocReply() NodeInfo *node = service.refreshMyNodeInfo(); // should guarantee there is now a position assert(node->has_position); - Position p = node->position; + // configuration of POSITION packet + // consider making this a function argument? + uint32_t pos_flags = radioConfig.preferences.position_flags; + + // Populate a Position struct with ONLY the requested fields + Position p = Position_init_default; // Start with an empty structure + + // lat/lon are unconditionally included - IF AVAILABLE! + p.latitude_i = node->position.latitude_i; + p.longitude_i = node->position.longitude_i; + p.time = node->position.time; + + if (pos_flags & PositionFlags_POS_BATTERY) + p.battery_level = node->position.battery_level; + + if (pos_flags & PositionFlags_POS_ALTITUDE) { + if (pos_flags & PositionFlags_POS_ALT_MSL) + p.altitude = node->position.altitude; + else + p.altitude_hae = node->position.altitude_hae; + + if (pos_flags & PositionFlags_POS_GEO_SEP) + p.alt_geoid_sep = node->position.alt_geoid_sep; + } + + if (pos_flags & PositionFlags_POS_DOP) { + if (pos_flags & PositionFlags_POS_HVDOP) { + p.HDOP = node->position.HDOP; + p.VDOP = node->position.VDOP; + } else + p.PDOP = node->position.PDOP; + } + + if (pos_flags & PositionFlags_POS_SATINVIEW) + p.sats_in_view = node->position.sats_in_view; + + if (pos_flags & PositionFlags_POS_TIMESTAMP) + p.pos_timestamp = node->position.pos_timestamp; + // Strip out any time information before sending packets to other nodes - to keep the wire size small (and because other // nodes shouldn't trust it anyways) Note: we allow a device with a local GPS to include the time, so that gpsless