SystemStatus - Add ephemeris detail info in Gnss Debug interface

Add ephemeris detail info in Gnss Debug interface. This new info
also comes up in NMEA stings. Requires a new QMI_LOC interface
that supports extended NMEA string TLV.

Change-Id: I5dc566fb210c06a443ed6c27e064377851ce83a5
CRs-Fixed: 2024594
This commit is contained in:
Katz Yamada 2017-04-27 13:46:09 -07:00
parent 9d80214901
commit 3eef3d7a6c
8 changed files with 500 additions and 113 deletions

View file

@ -30,6 +30,9 @@ namespace implementation {
using ::android::hardware::hidl_vec;
#define GNSS_DEBUG_UNKNOWN_UTC_TIME (1483228800ULL) // 1/1/2017 00:00 GMT
#define GNSS_DEBUG_UNKNOWN_UTC_TIME_UNC (1.57783680E17) // 5 years in ns
GnssDebug::GnssDebug(Gnss* gnss) : mGnss(gnss)
{
}
@ -42,7 +45,7 @@ GnssDebug::GnssDebug(Gnss* gnss) : mGnss(gnss)
*/
Return<void> GnssDebug::getDebugData(getDebugData_cb _hidl_cb)
{
LOC_LOGI("GnssDebug - 0317a");
LOC_LOGI("GnssDebug - 0426a");
DebugData data = { };
@ -57,35 +60,57 @@ Return<void> GnssDebug::getDebugData(getDebugData_cb _hidl_cb)
mGnss->getGnssInterface()->getDebugReport(reports);
// location block
if (reports.mLocation.mValid) {
data.position.valid = true;
data.position.latitudeDegrees = reports.mLocation.mLocation.latitude;
data.position.longitudeDegrees = reports.mLocation.mLocation.longitude;
data.position.altitudeMeters = reports.mLocation.mLocation.altitude;
data.position.speedMetersPerSec = (double)(reports.mLocation.mLocation.speed);
data.position.bearingDegrees = (double)(reports.mLocation.mLocation.bearing);
data.position.horizontalAccuracyMeters = (double)(reports.mLocation.mLocation.accuracy);
data.position.verticalAccuracyMeters = reports.mLocation.verticalAccuracyMeters;
data.position.speedAccuracyMetersPerSecond = reports.mLocation.speedAccuracyMetersPerSecond;
data.position.bearingAccuracyDegrees = reports.mLocation.bearingAccuracyDegrees;
LOC_LOGV("GnssDebug - lat=%f lon=%f", data.position.latitudeDegrees, data.position.longitudeDegrees);
data.position.speedMetersPerSec =
(double)(reports.mLocation.mLocation.speed);
data.position.bearingDegrees =
(double)(reports.mLocation.mLocation.bearing);
data.position.horizontalAccuracyMeters =
(double)(reports.mLocation.mLocation.accuracy);
data.position.verticalAccuracyMeters =
reports.mLocation.verticalAccuracyMeters;
data.position.speedAccuracyMetersPerSecond =
reports.mLocation.speedAccuracyMetersPerSecond;
data.position.bearingAccuracyDegrees =
reports.mLocation.bearingAccuracyDegrees;
LOC_LOGI("GnssDebug - lat=%f lon=%f",
data.position.latitudeDegrees, data.position.longitudeDegrees);
timeval tv_now, tv_report;
tv_report.tv_sec = reports.mLocation.mLocation.timestamp / 1000ULL;
tv_report.tv_usec = (reports.mLocation.mLocation.timestamp % 1000ULL) * 1000ULL;
tv_report.tv_usec =
(reports.mLocation.mLocation.timestamp % 1000ULL) * 1000ULL;
gettimeofday(&tv_now, NULL);
data.position.ageSeconds =
(tv_now.tv_sec - tv_report.tv_sec) + (float)((tv_now.tv_usec - tv_report.tv_usec)) / 1000000;
(tv_now.tv_sec - tv_report.tv_sec) +
(float)((tv_now.tv_usec - tv_report.tv_usec)) / 1000000;
LOC_LOGV("GnssDebug - time now=%lld:%lld", tv_now.tv_sec, tv_now.tv_usec);
LOC_LOGV("GnssDebug - time rep=%lld:%lld", tv_report.tv_sec, tv_report.tv_usec);
LOC_LOGV("GnssDebug - age=%f", data.position.ageSeconds);
LOC_LOGI("GnssDebug - time now=%lld:%lld", tv_now.tv_sec, tv_now.tv_usec);
LOC_LOGI("GnssDebug - time rep=%lld:%lld",tv_report.tv_sec, tv_report.tv_usec);
LOC_LOGI("GnssDebug - age=%f", data.position.ageSeconds);
}
else {
data.position.valid = false;
}
// time block
if (reports.mTime.mValid) {
data.time.timeEstimate = reports.mTime.timeEstimate;
data.time.timeUncertaintyNs = reports.mTime.timeUncertaintyNs;
LOC_LOGV("GnssDebug - timeestimate=%lld", data.time.timeEstimate);
data.time.frequencyUncertaintyNsPerSec =
reports.mTime.frequencyUncertaintyNsPerSec;
}
else {
data.time.timeEstimate = GNSS_DEBUG_UNKNOWN_UTC_TIME;
data.time.timeUncertaintyNs = (float)(GNSS_DEBUG_UNKNOWN_UTC_TIME_UNC);
data.time.frequencyUncertaintyNsPerSec = 0;
}
LOC_LOGI("GnssDebug - timeestimate=%lld", data.time.timeEstimate);
// satellite data block
SatelliteData s = { };
@ -94,18 +119,31 @@ Return<void> GnssDebug::getDebugData(getDebugData_cb _hidl_cb)
for (uint32_t i=0; i<reports.mSatelliteInfo.size(); i++) {
memset(&s, 0, sizeof(s));
s.svid = reports.mSatelliteInfo[i].svid;
convertGnssConstellationType(reports.mSatelliteInfo[i].constellation, s.constellation);
s.ephemerisType = SatelliteEphemerisType::NOT_AVAILABLE;
s.ephemerisAgeSeconds = reports.mSatelliteInfo[i].ephemerisAgeSeconds;
convertGnssConstellationType(
reports.mSatelliteInfo[i].constellation, s.constellation);
convertGnssEphemerisType(
reports.mSatelliteInfo[i].mEphemerisType, s.ephemerisType);
convertGnssEphemerisSource(
reports.mSatelliteInfo[i].mEphemerisSource, s.ephemerisSource);
convertGnssEphemerisHealth(
reports.mSatelliteInfo[i].mEphemerisHealth, s.ephemerisHealth);
s.ephemerisAgeSeconds =
reports.mSatelliteInfo[i].ephemerisAgeSeconds;
s.serverPredictionIsAvailable =
reports.mSatelliteInfo[i].serverPredictionIsAvailable;
s.serverPredictionAgeSeconds =
reports.mSatelliteInfo[i].serverPredictionAgeSeconds;
s_array.push_back(s);
}
data.satelliteDataArray = s_array;
LOC_LOGV("GnssDebug - satellite=%d", data.satelliteDataArray.size());
LOC_LOGI("GnssDebug - satellite=%d", data.satelliteDataArray.size());
// callback HIDL with collected debug data
_hidl_cb(data);
LOC_LOGV("GnssDebug - done");
LOC_LOGI("GnssDebug - done");
return Void();
}

View file

@ -87,12 +87,65 @@ void convertGnssConstellationType(GnssSvType& in, GnssConstellationType& out)
case GNSS_SV_TYPE_GALILEO:
out = GnssConstellationType::GALILEO;
break;
case GNSS_SV_TYPE_UNKNOWN:
default:
out = GnssConstellationType::UNKNOWN;
break;
}
}
void convertGnssEphemerisType(GnssEphemerisType& in, GnssDebug::SatelliteEphemerisType& out)
{
switch(in) {
case GNSS_EPH_TYPE_EPHEMERIS:
out = GnssDebug::SatelliteEphemerisType::EPHEMERIS;
break;
case GNSS_EPH_TYPE_ALMANAC:
out = GnssDebug::SatelliteEphemerisType::ALMANAC_ONLY;
break;
case GNSS_EPH_TYPE_UNKNOWN:
default:
out = GnssDebug::SatelliteEphemerisType::NOT_AVAILABLE;
break;
}
}
void convertGnssEphemerisSource(GnssEphemerisSource& in, GnssDebug::SatelliteEphemerisSource& out)
{
switch(in) {
case GNSS_EPH_SOURCE_DEMODULATED:
out = GnssDebug::SatelliteEphemerisSource::DEMODULATED;
break;
case GNSS_EPH_SOURCE_SUPL_PROVIDED:
out = GnssDebug::SatelliteEphemerisSource::SUPL_PROVIDED;
break;
case GNSS_EPH_SOURCE_OTHER_SERVER_PROVIDED:
out = GnssDebug::SatelliteEphemerisSource::OTHER_SERVER_PROVIDED;
break;
case GNSS_EPH_SOURCE_LOCAL:
case GNSS_EPH_SOURCE_UNKNOWN:
default:
out = GnssDebug::SatelliteEphemerisSource::OTHER;
break;
}
}
void convertGnssEphemerisHealth(GnssEphemerisHealth& in, GnssDebug::SatelliteEphemerisHealth& out)
{
switch(in) {
case GNSS_EPH_HEALTH_GOOD:
out = GnssDebug::SatelliteEphemerisHealth::GOOD;
break;
case GNSS_EPH_HEALTH_BAD:
out = GnssDebug::SatelliteEphemerisHealth::BAD;
break;
case GNSS_EPH_HEALTH_UNKNOWN:
default:
out = GnssDebug::SatelliteEphemerisHealth::UNKNOWN;
break;
}
}
} // namespace implementation
} // namespace V1_0
} // namespace gnss

View file

@ -32,6 +32,7 @@
#include <android/hardware/gnss/1.0/types.h>
#include <LocationAPI.h>
#include <GnssDebug.h>
namespace android {
namespace hardware {
@ -41,6 +42,9 @@ namespace implementation {
void convertGnssLocation(Location& in, GnssLocation& out);
void convertGnssConstellationType(GnssSvType& in, GnssConstellationType& out);
void convertGnssEphemerisType(GnssEphemerisType& in, GnssDebug::SatelliteEphemerisType& out);
void convertGnssEphemerisSource(GnssEphemerisSource& in, GnssDebug::SatelliteEphemerisSource& out);
void convertGnssEphemerisHealth(GnssEphemerisHealth& in, GnssDebug::SatelliteEphemerisHealth& out);
} // namespace implementation
} // namespace V1_0

View file

@ -113,6 +113,8 @@ public:
double mAgcGlo; // x14
double mAgcBds; // x15
double mAgcGal; // x16
int32_t mLeapSeconds;// x17
int32_t mLeapSecUnc; // x18
};
// parser
@ -144,7 +146,9 @@ private:
eAgcGlo = 20,
eAgcBds = 21,
eAgcGal = 22,
eMax = eRecErrorRecovery
eLeapSeconds = 23,
eLeapSecUnc = 24,
eMax
};
SystemStatusPQWM1 mM1;
@ -171,11 +175,14 @@ public:
inline uint32_t getAgcBds() { return mM1.mAgcBds; }
inline uint32_t getAgcGal() { return mM1.mAgcGal; }
inline uint32_t getRecErrorRecovery() { return mM1.mRecErrorRecovery; }
inline int32_t getLeapSeconds(){ return mM1.mLeapSeconds; }
inline int32_t getLeapSecUnc() { return mM1.mLeapSecUnc; }
SystemStatusPQWM1parser(const char *str_in, uint32_t len_in)
: SystemStatusNmeaBase(str_in, len_in)
{
if (mField.size() < eMax) {
LOC_LOGE("PQWM1parser - invalid size=%d", mField.size());
return;
}
memset(&mM1, 0, sizeof(mM1));
@ -201,6 +208,8 @@ public:
mM1.mAgcGlo = atof(mField[eAgcGlo].c_str());
mM1.mAgcBds = atof(mField[eAgcBds].c_str());
mM1.mAgcGal = atof(mField[eAgcGal].c_str());
mM1.mLeapSeconds = atoi(mField[eLeapSeconds].c_str());
mM1.mLeapSecUnc = atoi(mField[eLeapSecUnc].c_str());
}
inline SystemStatusPQWM1& get() { return mM1;} //getparser
@ -235,7 +244,7 @@ private:
eEpiHepe = 6,
eEpiAltUnc = 7,
eEpiSrc = 8,
eMax = eEpiSrc
eMax
};
SystemStatusPQWP1 mP1;
@ -292,7 +301,7 @@ private:
eBestAlt = 4,
eBestHepe = 5,
eBestAltUnc = 6,
eMax = eBestAltUnc
eMax
};
SystemStatusPQWP2 mP2;
@ -357,7 +366,7 @@ private:
eBdsXtraValid = 10,
eGalXtraValid = 11,
eQzssXtraValid = 12,
eMax = eQzssXtraValid
eMax
};
SystemStatusPQWP3 mP3;
@ -422,7 +431,7 @@ private:
eBdsEpheValid = 4,
eGalEpheValid = 5,
eQzssEpheValid = 6,
eMax = eQzssEpheValid
eMax
};
SystemStatusPQWP4 mP4;
@ -495,7 +504,7 @@ private:
eBdsBadMask = 14,
eGalBadMask = 15,
eQzssBadMask = 16,
eMax = eQzssBadMask
eMax
};
SystemStatusPQWP5 mP5;
@ -560,7 +569,7 @@ private:
eTalker = 0,
eUtcTime = 1,
eFixInfoMask = 2,
eMax = eFixInfoMask
eMax
};
SystemStatusPQWP6 mP6;
@ -580,6 +589,44 @@ public:
inline SystemStatusPQWP6& get() { return mP6;}
};
/******************************************************************************
SystemStatusPQWP7parser
******************************************************************************/
class SystemStatusPQWP7
{
public:
SystemStatusNav mNav[SV_ALL_NUM];
};
class SystemStatusPQWP7parser : public SystemStatusNmeaBase
{
private:
enum
{
eTalker = 0,
eUtcTime = 1,
eMax = 2 + SV_ALL_NUM*3
};
SystemStatusPQWP7 mP7;
public:
SystemStatusPQWP7parser(const char *str_in, uint32_t len_in)
: SystemStatusNmeaBase(str_in, len_in)
{
if (mField.size() < eMax) {
LOC_LOGE("PQWP7parser - invalid size=%d", mField.size());
return;
}
for (uint32_t i=0; i<SV_ALL_NUM; i++) {
mP7.mNav[i].mType = GnssEphemerisType(atoi(mField[i*3+2].c_str()));
mP7.mNav[i].mSource = GnssEphemerisSource(atoi(mField[i*3+3].c_str()));
mP7.mNav[i].mAgeSec = atoi(mField[i*3+4].c_str());
}
}
inline SystemStatusPQWP7& get() { return mP7;}
};
/******************************************************************************
SystemStatusPQWS1parser
******************************************************************************/
@ -599,7 +646,7 @@ private:
eUtcTime = 1,
eFixInfoMask = 2,
eHepeLimit = 3,
eMax = eHepeLimit
eMax
};
SystemStatusPQWS1 mS1;
@ -631,7 +678,9 @@ SystemStatusTimeAndClock::SystemStatusTimeAndClock(const SystemStatusPQWM1& nmea
mTimeSource(nmea.mTimeSource),
mTimeUnc(nmea.mTimeUnc),
mClockFreqBias(nmea.mClockFreqBias),
mClockFreqBiasUnc(nmea.mClockFreqBiasUnc)
mClockFreqBiasUnc(nmea.mClockFreqBiasUnc),
mLeapSeconds(nmea.mLeapSeconds),
mLeapSecUnc(nmea.mLeapSecUnc)
{
}
@ -643,7 +692,9 @@ bool SystemStatusTimeAndClock::equals(SystemStatusTimeAndClock& peer)
(mTimeSource != peer.mTimeSource) ||
(mTimeUnc != peer.mTimeUnc) ||
(mClockFreqBias != peer.mClockFreqBias) ||
(mClockFreqBiasUnc != peer.mClockFreqBiasUnc)) {
(mClockFreqBiasUnc != peer.mClockFreqBiasUnc) ||
(mLeapSeconds != peer.mLeapSeconds) ||
(mLeapSecUnc != peer.mLeapSecUnc)) {
return false;
}
return true;
@ -651,7 +702,7 @@ bool SystemStatusTimeAndClock::equals(SystemStatusTimeAndClock& peer)
void SystemStatusTimeAndClock::dump()
{
LOC_LOGV("TimeAndClock: u=%ld:%ld g=%d:%d v=%d s=%d u=%d b=%d bu=%d",
LOC_LOGV("TimeAndClock: u=%ld:%ld g=%d:%d v=%d ts=%d tu=%d b=%d bu=%d ls=%d lu=%d",
mUtcTime.tv_sec, mUtcTime.tv_nsec,
mGpsWeek,
mGpsTowMs,
@ -659,7 +710,9 @@ void SystemStatusTimeAndClock::dump()
mTimeSource,
mTimeUnc,
mClockFreqBias,
mClockFreqBiasUnc);
mClockFreqBiasUnc,
mLeapSeconds,
mLeapSecUnc);
return;
}
@ -1031,6 +1084,39 @@ void SystemStatusPdr::dump()
return;
}
/******************************************************************************
SystemStatusNavData
******************************************************************************/
SystemStatusNavData::SystemStatusNavData(const SystemStatusPQWP7& nmea)
{
for (uint32_t i=0; i<SV_ALL_NUM; i++) {
mNav[i] = nmea.mNav[i];
}
}
bool SystemStatusNavData::equals(SystemStatusNavData& peer)
{
for (uint32_t i=0; i<SV_ALL_NUM; i++) {
if ((mNav[i].mType != peer.mNav[i].mType) ||
(mNav[i].mSource != peer.mNav[i].mSource) ||
(mNav[i].mAgeSec != peer.mNav[i].mAgeSec)) {
return false;
}
}
return true;
}
void SystemStatusNavData::dump()
{
LOC_LOGV("NavData: u=%ld:%ld",
mUtcTime.tv_sec, mUtcTime.tv_nsec);
for (uint32_t i=0; i<SV_ALL_NUM; i++) {
LOC_LOGV("i=%d type=%d src=%d age=%d",
i, mNav[i].mType, mNav[i].mSource, mNav[i].mAgeSec);
}
return;
}
/******************************************************************************
SystemStatusPositionFailure
******************************************************************************/
@ -1101,6 +1187,8 @@ SystemStatus::SystemStatus()
mCache.mEphemeris.clear();
mCache.mSvHealth.clear();
mCache.mPdr.clear();
mCache.mNavData.clear();
mCache.mPositionFailure.clear();
}
@ -1250,6 +1338,20 @@ bool SystemStatus::setPdr(const SystemStatusPQWP6& nmea)
return true;
}
bool SystemStatus::setNavData(const SystemStatusPQWP7& nmea)
{
SystemStatusNavData s(nmea);
if (!mCache.mNavData.empty() && mCache.mNavData.back().equals(s)) {
mCache.mNavData.back().mUtcReported = s.mUtcReported;
} else {
mCache.mNavData.push_back(s);
if (mCache.mNavData.size() > maxNavData) {
mCache.mNavData.erase(mCache.mNavData.begin());
}
}
return true;
}
/******************************************************************************
SystemStatus - Sx functions
******************************************************************************/
@ -1283,6 +1385,7 @@ static uint32_t cnt_p3 = 0;
static uint32_t cnt_p4 = 0;
static uint32_t cnt_p5 = 0;
static uint32_t cnt_p6 = 0;
static uint32_t cnt_p7 = 0;
static uint32_t cnt_s1 = 0;
bool SystemStatus::setNmeaString(const char *data, uint32_t len)
@ -1293,7 +1396,7 @@ bool SystemStatus::setNmeaString(const char *data, uint32_t len)
}
char buf[SystemStatusNmeaBase::NMEA_MAXSIZE + 1] = { 0 };
strlcpy(buf, data, sizeof(buf));
strlcpy(buf, data, (len < strlen(data))? len : strlen(data));
pthread_mutex_lock(&mMutexSystemStatus);
@ -1330,6 +1433,10 @@ bool SystemStatus::setNmeaString(const char *data, uint32_t len)
ret = setPdr(SystemStatusPQWP6parser(buf, len).get());
cnt_p6++;
}
else if (0 == strncmp(data, "$PQWP7", SystemStatusNmeaBase::NMEA_MINSIZE)) {
ret = setNavData(SystemStatusPQWP7parser(buf, len).get());
cnt_p7++;
}
else if (0 == strncmp(data, "$PQWS1", SystemStatusNmeaBase::NMEA_MINSIZE)) {
ret = setPositionFailure(SystemStatusPQWS1parser(buf, len).get());
cnt_s1++;
@ -1338,7 +1445,7 @@ bool SystemStatus::setNmeaString(const char *data, uint32_t len)
// do nothing
}
cnt++;
LOC_LOGV("setNmeaString: cnt=%d M:%d 1:%d 2:%d 3:%d 4:%d 5:%d 6:%d S:%d",
LOC_LOGV("setNmeaString: cnt=%d M:%d 1:%d 2:%d 3:%d 4:%d 5:%d 6:%d 7:%d S:%d",
cnt,
cnt_m1,
cnt_p1,
@ -1347,6 +1454,7 @@ bool SystemStatus::setNmeaString(const char *data, uint32_t len)
cnt_p4,
cnt_p5,
cnt_p6,
cnt_p7,
cnt_s1);
pthread_mutex_unlock(&mMutexSystemStatus);
@ -1364,19 +1472,20 @@ bool SystemStatus::eventPosition(const UlpLocation& location,
const GpsLocationExtended& locationEx)
{
SystemStatusLocation s(location, locationEx);
if ((mCache.mLocation.empty()) || !mCache.mLocation.back().equals(s)) {
if (!mCache.mLocation.empty() && mCache.mLocation.back().equals(s)) {
mCache.mLocation.back().mUtcReported = s.mUtcReported;
}
else {
mCache.mLocation.push_back(s);
if (mCache.mLocation.size() > maxLocation) {
mCache.mLocation.erase(mCache.mLocation.begin());
}
}
LOC_LOGV("eventPosition - lat=%f lon=%f alt=%f speed=%f",
s.mLocation.gpsLocation.latitude,
s.mLocation.gpsLocation.longitude,
s.mLocation.gpsLocation.altitude,
s.mLocation.gpsLocation.speed);
}
return true;
}
@ -1451,6 +1560,12 @@ bool SystemStatus::getReport(SystemStatusReports& report, bool isLatestOnly) con
report.mPdr.push_back(mCache.mPdr.back());
report.mPdr.back().dump();
}
report.mNavData.clear();
if (mCache.mNavData.size() >= 1) {
report.mNavData.push_back(mCache.mNavData.back());
report.mNavData.back().dump();
}
report.mPositionFailure.clear();
if (mCache.mPositionFailure.size() >= 1) {
report.mPositionFailure.push_back(mCache.mPositionFailure.back());
@ -1472,6 +1587,8 @@ bool SystemStatus::getReport(SystemStatusReports& report, bool isLatestOnly) con
report.mEphemeris.clear();
report.mSvHealth.clear();
report.mPdr.clear();
report.mNavData.clear();
report.mPositionFailure.clear();
report = mCache;
}

View file

@ -33,12 +33,20 @@
#include <vector>
#include <gps_extended_c.h>
#define GPS_MIN (1)
#define GPS_MIN (1) //1-32
#define SBAS_MIN (33)
#define GLO_MIN (65)
#define BDS_MIN (201)
#define QZSS_MIN (193)
#define GAL_MIN (301)
#define GLO_MIN (65) //65-88
#define QZSS_MIN (193) //193-197
#define BDS_MIN (201) //201-237
#define GAL_MIN (301) //301-336
#define GPS_NUM (32)
#define SBAS_NUM (32)
#define GLO_NUM (24)
#define QZSS_NUM (5)
#define BDS_NUM (37)
#define GAL_NUM (36)
#define SV_ALL_NUM (GPS_NUM+GLO_NUM+QZSS_NUM+BDS_NUM+GAL_NUM) //=134
namespace loc_core
{
@ -87,6 +95,8 @@ public:
int32_t mTimeUnc;
int32_t mClockFreqBias;
int32_t mClockFreqBiasUnc;
int32_t mLeapSeconds;
int32_t mLeapSecUnc;
SystemStatusTimeAndClock(const SystemStatusPQWM1& nmea);
bool equals(SystemStatusTimeAndClock& peer);
void dump(void);
@ -229,6 +239,23 @@ public:
void dump(void);
};
class SystemStatusPQWP7;
struct SystemStatusNav
{
GnssEphemerisType mType;
GnssEphemerisSource mSource;
int32_t mAgeSec;
};
class SystemStatusNavData : public SystemStatusItemBase
{
public:
SystemStatusNav mNav[SV_ALL_NUM];
SystemStatusNavData(const SystemStatusPQWP7& nmea);
bool equals(SystemStatusNavData& peer);
void dump(void);
};
class SystemStatusPQWS1;
class SystemStatusPositionFailure : public SystemStatusItemBase
{
@ -259,6 +286,8 @@ public:
std::vector<SystemStatusEphemeris> mEphemeris;
std::vector<SystemStatusSvHealth> mSvHealth;
std::vector<SystemStatusPdr> mPdr;
std::vector<SystemStatusNavData> mNavData;
std::vector<SystemStatusPositionFailure> mPositionFailure;
};
@ -282,6 +311,8 @@ class SystemStatus
static const uint32_t maxEphemeris = 5;
static const uint32_t maxSvHealth = 5;
static const uint32_t maxPdr = 5;
static const uint32_t maxNavData = 5;
static const uint32_t maxPositionFailure = 5;
SystemStatusReports mCache;
@ -299,6 +330,8 @@ class SystemStatus
bool setEphemeris(const SystemStatusPQWP4& nmea);
bool setSvHealth(const SystemStatusPQWP5& nmea);
bool setPdr(const SystemStatusPQWP6& nmea);
bool setNavData(const SystemStatusPQWP7& nmea);
bool setPositionFailure(const SystemStatusPQWS1& nmea);
public:

View file

@ -2599,57 +2599,133 @@ void GnssAdapter::convertSatelliteInfo(std::vector<GnssDebugSatelliteInfo>& out,
const GnssSvType& in_constellation,
const SystemStatusReports& in)
{
GnssDebugSatelliteInfo s = {};
uint64_t mask = 0ULL;
float age = 0.0;
uint64_t sv_mask = 0ULL;
uint32_t svid_min = 0;
uint32_t mask_size = 0;
uint32_t svid_num = 0;
uint32_t svid_idx = 0;
uint64_t eph_health_good_mask = 0ULL;
uint64_t eph_health_bad_mask = 0ULL;
uint64_t server_perdiction_available_mask = 0ULL;
float server_perdiction_age = 0.0f;
// set constellationi based parameters
switch (in_constellation) {
case GNSS_SV_TYPE_GPS:
svid_min = GPS_MIN;
mask_size = 32;
svid_num = GPS_NUM;
svid_idx = 0;
if (!in.mSvHealth.empty()) {
eph_health_good_mask = in.mSvHealth.back().mGpsGoodMask;
eph_health_bad_mask = in.mSvHealth.back().mGpsBadMask;
}
if (!in.mXtra.empty()) {
server_perdiction_available_mask = in.mXtra.back().mGpsXtraValid;
server_perdiction_age = (float)(in.mXtra.back().mGpsXtraAge);
}
break;
case GNSS_SV_TYPE_GLONASS:
svid_min = GLO_MIN;
mask_size = 32;
break;
case GNSS_SV_TYPE_BEIDOU:
svid_min = BDS_MIN;
mask_size = 64;
svid_num = GLO_NUM;
svid_idx = GPS_NUM;
if (!in.mSvHealth.empty()) {
eph_health_good_mask = in.mSvHealth.back().mGloGoodMask;
eph_health_bad_mask = in.mSvHealth.back().mGloBadMask;
}
if (!in.mXtra.empty()) {
server_perdiction_available_mask = in.mXtra.back().mGloXtraValid;
server_perdiction_age = (float)(in.mXtra.back().mGloXtraAge);
}
break;
case GNSS_SV_TYPE_QZSS:
svid_min = QZSS_MIN;
mask_size = 32;
svid_num = QZSS_NUM;
svid_idx = GPS_NUM+GLO_NUM;
if (!in.mSvHealth.empty()) {
eph_health_good_mask = in.mSvHealth.back().mQzssGoodMask;
eph_health_bad_mask = in.mSvHealth.back().mQzssBadMask;
}
if (!in.mXtra.empty()) {
server_perdiction_available_mask = in.mXtra.back().mQzssXtraValid;
server_perdiction_age = (float)(in.mXtra.back().mQzssXtraAge);
}
break;
case GNSS_SV_TYPE_BEIDOU:
svid_min = BDS_MIN;
svid_num = BDS_NUM;
svid_idx = GPS_NUM+GLO_NUM+QZSS_NUM;
if (!in.mSvHealth.empty()) {
eph_health_good_mask = in.mSvHealth.back().mBdsGoodMask;
eph_health_bad_mask = in.mSvHealth.back().mBdsBadMask;
}
if (!in.mXtra.empty()) {
server_perdiction_available_mask = in.mXtra.back().mBdsXtraValid;
server_perdiction_age = (float)(in.mXtra.back().mBdsXtraAge);
}
break;
case GNSS_SV_TYPE_GALILEO:
svid_min = GAL_MIN;
mask_size = 64;
svid_num = GAL_NUM;
svid_idx = GPS_NUM+GLO_NUM+QZSS_NUM+BDS_NUM;
if (!in.mSvHealth.empty()) {
eph_health_good_mask = in.mSvHealth.back().mGalGoodMask;
eph_health_bad_mask = in.mSvHealth.back().mGalBadMask;
}
if (!in.mXtra.empty()) {
server_perdiction_available_mask = in.mXtra.back().mGalXtraValid;
server_perdiction_age = (float)(in.mXtra.back().mGalXtraAge);
}
break;
default:
return;
}
if(!in.mEphemeris.empty()) {
mask = in.mEphemeris.back().mGpsEpheValid;
if(!in.mXtra.empty()) {
age = (float)(in.mXtra.back().mGpsXtraAge);
}
else {
age = 0.0;
}
// extract each sv info from systemstatus report
for(uint32_t i=0; i<svid_num; i++) {
for(uint32_t i=0; i<mask_size; i++) {
if (0 != (mask & (1<<i))) {
GnssDebugSatelliteInfo s = {};
s.size = sizeof(s);
s.svid = i + svid_min;
s.constellation = in_constellation;
s.ephemerisType = 0;
s.ephemerisAgeSeconds = age;
if (!in.mNavData.empty()) {
s.mEphemerisType = in.mNavData.back().mNav[svid_idx+i].mType;
s.mEphemerisSource = in.mNavData.back().mNav[svid_idx+i].mSource;
}
else {
s.mEphemerisType = GNSS_EPH_TYPE_UNKNOWN;
s.mEphemerisSource = GNSS_EPH_SOURCE_UNKNOWN;
}
sv_mask = 0x1ULL << i;
if (eph_health_good_mask & sv_mask) {
s.mEphemerisHealth = GNSS_EPH_HEALTH_GOOD;
}
else if (eph_health_bad_mask & sv_mask) {
s.mEphemerisHealth = GNSS_EPH_HEALTH_BAD;
}
else {
s.mEphemerisHealth = GNSS_EPH_HEALTH_UNKNOWN;
}
if (!in.mNavData.empty()) {
s.ephemerisAgeSeconds =
(float)(in.mNavData.back().mNav[svid_idx+i].mAgeSec);
}
else {
s.ephemerisAgeSeconds = 0.0f;
}
if (server_perdiction_available_mask & sv_mask) {
s.serverPredictionIsAvailable = true;
}
else {
s.serverPredictionIsAvailable = false;
}
s.serverPredictionAgeSeconds = server_perdiction_age;
out.push_back(s);
}
}
}
return;
}
@ -2671,45 +2747,83 @@ bool GnssAdapter::getDebugReport(GnssDebugReport& r)
// location block
r.mLocation.size = sizeof(r.mLocation);
if(!reports.mLocation.empty()) {
r.mLocation.mLocation.latitude = reports.mLocation.back().mLocation.gpsLocation.latitude;
r.mLocation.mLocation.longitude = reports.mLocation.back().mLocation.gpsLocation.longitude;
r.mLocation.mLocation.altitude = reports.mLocation.back().mLocation.gpsLocation.altitude;
r.mLocation.mLocation.speed = (double)(reports.mLocation.back().mLocation.gpsLocation.speed);
r.mLocation.mLocation.bearing = (double)(reports.mLocation.back().mLocation.gpsLocation.bearing);
r.mLocation.mLocation.accuracy = (double)(reports.mLocation.back().mLocation.gpsLocation.accuracy);
r.mLocation.mValid = true;
r.mLocation.mLocation.latitude =
reports.mLocation.back().mLocation.gpsLocation.latitude;
r.mLocation.mLocation.longitude =
reports.mLocation.back().mLocation.gpsLocation.longitude;
r.mLocation.mLocation.altitude =
reports.mLocation.back().mLocation.gpsLocation.altitude;
r.mLocation.mLocation.speed =
(double)(reports.mLocation.back().mLocation.gpsLocation.speed);
r.mLocation.mLocation.bearing =
(double)(reports.mLocation.back().mLocation.gpsLocation.bearing);
r.mLocation.mLocation.accuracy =
(double)(reports.mLocation.back().mLocation.gpsLocation.accuracy);
r.mLocation.verticalAccuracyMeters = reports.mLocation.back().mLocationEx.vert_unc;
r.mLocation.speedAccuracyMetersPerSecond = reports.mLocation.back().mLocationEx.speed_unc;
r.mLocation.bearingAccuracyDegrees = reports.mLocation.back().mLocationEx.bearing_unc;
r.mLocation.verticalAccuracyMeters =
reports.mLocation.back().mLocationEx.vert_unc;
r.mLocation.speedAccuracyMetersPerSecond =
reports.mLocation.back().mLocationEx.speed_unc;
r.mLocation.bearingAccuracyDegrees =
reports.mLocation.back().mLocationEx.bearing_unc;
r.mLocation.mLocation.timestamp =
reports.mLocation.back().mLocation.gpsLocation.timestamp;
}
else if(!reports.mBestPosition.empty()) {
r.mLocation.mLocation.latitude = (double)(reports.mBestPosition.back().mBestLat);
r.mLocation.mLocation.longitude = (double)(reports.mBestPosition.back().mBestLon);
r.mLocation.mLocation.altitude = reports.mBestPosition.back().mBestAlt;
r.mLocation.mValid = true;
r.mLocation.mLocation.latitude =
(double)(reports.mBestPosition.back().mBestLat);
r.mLocation.mLocation.longitude =
(double)(reports.mBestPosition.back().mBestLon);
r.mLocation.mLocation.altitude =
reports.mBestPosition.back().mBestAlt;
r.mLocation.mLocation.timestamp =
reports.mBestPosition.back().mUtcReported.tv_sec * 1000ULL +
reports.mBestPosition.back().mUtcReported.tv_nsec / 1000000ULL;
}
else {
r.mLocation.mValid = false;
}
if (r.mLocation.mValid) {
LOC_LOGV("getDebugReport - lat=%f lon=%f alt=%f speed=%f",
r.mLocation.mLocation.latitude,
r.mLocation.mLocation.longitude,
r.mLocation.mLocation.altitude,
r.mLocation.mLocation.speed);
}
// time block
r.mTime.size = sizeof(r.mTime);
if(!reports.mBestPosition.empty()) {
r.mTime.timeEstimate = reports.mBestPosition.back().mUtcTime.tv_sec;
}
if(!reports.mTimeAndClock.empty()) {
r.mTime.timeUncertaintyNs = (float)(reports.mTimeAndClock.back().mTimeUnc);
r.mTime.mValid = true;
r.mTime.timeEstimate =
(((int64_t)(reports.mTimeAndClock.back().mGpsWeek)*7 +
GNSS_UTC_TIME_OFFSET)*24*60*60 +
(int64_t)(reports.mTimeAndClock.back().mLeapSeconds))*1000ULL +
(int64_t)(reports.mTimeAndClock.back().mGpsTowMs);
r.mTime.timeUncertaintyNs =
(float)((reports.mTimeAndClock.back().mTimeUnc +
reports.mTimeAndClock.back().mLeapSecUnc)*1000);
r.mTime.frequencyUncertaintyNsPerSec =
(float)(reports.mTimeAndClock.back().mClockFreqBiasUnc);
LOC_LOGV("getDebugReport - timeestimate=%ld", r.mTime.timeEstimate);
}
else {
r.mTime.mValid = false;
}
LOC_LOGV("getDebugReport - timeestimate=%lld", r.mTime.timeEstimate);
// satellite info block
convertSatelliteInfo(r.mSatelliteInfo, GNSS_SV_TYPE_GPS, reports);
convertSatelliteInfo(r.mSatelliteInfo, GNSS_SV_TYPE_GLONASS, reports);
convertSatelliteInfo(r.mSatelliteInfo, GNSS_SV_TYPE_BEIDOU, reports);
convertSatelliteInfo(r.mSatelliteInfo, GNSS_SV_TYPE_QZSS, reports);
convertSatelliteInfo(r.mSatelliteInfo, GNSS_SV_TYPE_BEIDOU, reports);
convertSatelliteInfo(r.mSatelliteInfo, GNSS_SV_TYPE_GALILEO, reports);
LOC_LOGV("getDebugReport - satellite=%d", r.mSatelliteInfo.size());
LOC_LOGV("getDebugReport - satellite=%lu", r.mSatelliteInfo.size());
return true;
}

View file

@ -37,6 +37,7 @@
#define GNSS_NI_MESSAGE_ID_MAX 2048
#define GNSS_SV_MAX 64
#define GNSS_MEASUREMENTS_MAX 64
#define GNSS_UTC_TIME_OFFSET (3657)
typedef enum {
LOCATION_ERROR_SUCCESS = 0,
@ -250,6 +251,26 @@ typedef enum {
GNSS_SV_TYPE_GALILEO,
} GnssSvType;
typedef enum {
GNSS_EPH_TYPE_UNKNOWN = 0,
GNSS_EPH_TYPE_EPHEMERIS,
GNSS_EPH_TYPE_ALMANAC,
} GnssEphemerisType;
typedef enum {
GNSS_EPH_SOURCE_UNKNOWN = 0,
GNSS_EPH_SOURCE_DEMODULATED,
GNSS_EPH_SOURCE_SUPL_PROVIDED,
GNSS_EPH_SOURCE_OTHER_SERVER_PROVIDED,
GNSS_EPH_SOURCE_LOCAL,
} GnssEphemerisSource;
typedef enum {
GNSS_EPH_HEALTH_UNKNOWN = 0,
GNSS_EPH_HEALTH_GOOD,
GNSS_EPH_HEALTH_BAD,
} GnssEphemerisHealth;
typedef uint16_t GnssSvOptionsMask;
typedef enum {
GNSS_SV_OPTIONS_HAS_EPHEMER_BIT = (1<<0),
@ -558,6 +579,7 @@ typedef struct {
typedef struct {
size_t size; // set to sizeof
bool mValid;
Location mLocation;
double verticalAccuracyMeters;
double speedAccuracyMetersPerSecond;
@ -566,16 +588,22 @@ typedef struct {
typedef struct {
size_t size; // set to sizeof
bool mValid;
int64_t timeEstimate;
float timeUncertaintyNs;
float frequencyUncertaintyNsPerSec;
} GnssDebugTime;
typedef struct {
size_t size; // set to sizeof
uint32_t svid;
GnssSvType constellation;
uint32_t ephemerisType;
GnssEphemerisType mEphemerisType;
GnssEphemerisSource mEphemerisSource;
GnssEphemerisHealth mEphemerisHealth;
float ephemerisAgeSeconds;
bool serverPredictionIsAvailable;
float serverPredictionAgeSeconds;
} GnssDebugSatelliteInfo;
typedef struct {

View file

@ -44,7 +44,7 @@ void loc_nmea_generate_pos(const UlpLocation &location,
std::vector<std::string> &nmeaArraystr);
#define DEBUG_NMEA_MINSIZE 6
#define DEBUG_NMEA_MAXSIZE 256
#define DEBUG_NMEA_MAXSIZE 4096
inline bool loc_nmea_is_debug(const char* nmea, int length) {
return ((nullptr != nmea) &&
(length >= DEBUG_NMEA_MINSIZE) && (length <= DEBUG_NMEA_MAXSIZE) &&