Skip to content
Merged
Show file tree
Hide file tree
Changes from 14 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion src/OpenBikeSensorFirmware.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -446,7 +446,6 @@ void setup() {
gps.handle();

setupBluetooth(cfg, trackUniqueIdentifier);

obsDisplay->showTextOnGrid(2, obsDisplay->newLine(), "Wait for GPS");
obsDisplay->newLine();
gps.handle();
Expand Down
17 changes: 16 additions & 1 deletion src/configServer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,9 @@ static const char* const development =
static const char* const rebootIndex =
"<h3>Device reboots now.</h3>";

static const char* const gpsColdIndex =
"<h3>GPS cold start</h3>";

// #########################################
// Wifi
// #########################################
Expand Down Expand Up @@ -456,6 +459,7 @@ static void handleNotFound(HTTPRequest * req, HTTPResponse * res);
static void handleIndex(HTTPRequest * req, HTTPResponse * res);
static void handleAbout(HTTPRequest * req, HTTPResponse * res);
static void handleReboot(HTTPRequest * req, HTTPResponse * res);
static void handleColdStartGPS(HTTPRequest * req, HTTPResponse * res);
static void handleBackup(HTTPRequest * req, HTTPResponse * res);
static void handleBackupDownload(HTTPRequest * req, HTTPResponse * res);
static void handleBackupRestore(HTTPRequest * req, HTTPResponse * res);
Expand Down Expand Up @@ -546,6 +550,7 @@ void registerPages(HTTPServer * httpServer) {
httpServer->registerNode(new ResourceNode("/", HTTP_GET, handleIndex));
httpServer->registerNode(new ResourceNode("/about", HTTP_GET, handleAbout));
httpServer->registerNode(new ResourceNode("/reboot", HTTP_GET, handleReboot));
httpServer->registerNode(new ResourceNode("/cold", HTTP_GET, handleColdStartGPS));
httpServer->registerNode(new ResourceNode("/settings/backup", HTTP_GET, handleBackup));
httpServer->registerNode(new ResourceNode("/settings/backup.json", HTTP_GET, handleBackupDownload));
httpServer->registerNode(new ResourceNode("/settings/restore", HTTP_POST, handleBackupRestore));
Expand Down Expand Up @@ -724,7 +729,7 @@ static void wifiConnectedActions() {
if (WiFiClass::status() == WL_CONNECTED) {
TimeUtils::setClockByNtpAndWait(WiFi.gatewayIP().toString().c_str());
}
if (SD.begin() && WiFiClass::status() == WL_CONNECTED) {
if (SD.begin() && WiFiClass::status() == WL_CONNECTED && gps.is_neo6()) {
AlpData::update(obsDisplay);
}

Expand Down Expand Up @@ -1065,6 +1070,8 @@ static void handleAbout(HTTPRequest *req, HTTPResponse * res) {
page += keyValue("GPS satellites", gps.getValidSatellites());
page += keyValue("GPS uptime", gps.getUptime(), "ms");
page += keyValue("GPS noise level", gps.getLastNoiseLevel());
page += keyValue("GPS Antenna Gain", gps.getLastAntennaGain());
page += keyValue("GPS Jamming Level", gps.getLastJamInd());
page += keyValue("GPS baud rate", gps.getBaudRate());
page += keyValue("GPS ALP bytes", gps.getNumberOfAlpBytesSent());
page += keyValue("GPS messages", gps.getMessagesHtml());
Expand Down Expand Up @@ -1123,6 +1130,14 @@ static void handleReboot(HTTPRequest *, HTTPResponse * res) {
ESP.restart();
}

static void handleColdStartGPS(HTTPRequest *, HTTPResponse * res) {
String html = createPage(gpsColdIndex);
html = replaceDefault(html, "Navigation");
sendHtml(res, html);
gps.coldStartGps();
res->finalize();
}


static void handleBackup(HTTPRequest *, HTTPResponse * res) {
String html = createPage(backupIndex, xhrUpload);
Expand Down
147 changes: 123 additions & 24 deletions src/gps.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,14 +31,63 @@ const String Gps::INF_SEVERITY_STRING[] = {
String("TST"), String("DBG")
};

bool Gps::is_neo6() const {
if (String(hwString).substring(0,4) == String("0004")) {
return true;
}
return false;
}

bool Gps::is_neo8() const {
if (String(hwString).substring(0,4) == String("0008")) {
return true;
}
return false;
}

bool Gps::is_neo10() const {
if (String(hwString).substring(0,4) == String("000A")) {
return true;
}
return false;
}

String Gps::hw() const {
if (is_neo6()){
return "Neo6";
}
if (is_neo8()){
return "Neo8";
}
if (is_neo10()) {
return "NeoA";
}
return "Neo" + String(hwString).substring(3,4);
}

void Gps::begin() {
setBaud();
softResetGps();
if (mGpsNeedsConfigUpdate) {
configureGpsModule();
}
enableAlpIfDataIsAvailable();
pollStatistics();
if((!is_neo6()) || (!SD.exists(AID_INI_DATA_FILE_NAME))) {
// we're on a non-6 neo and avoid AID_INI because is deprecated
// or we're on a neo6 but last boot we didn't get far enough to receive fresh
// ALP_INI data after initializing
// so restart GPS for good measure.
if (is_neo6()) log_i("We found no AID_INI on with neo6 on boot - coldstart gps in case its in a state where it doesn't get fixes");
if (!is_neo6()) log_i("Coldstart because we found that newer neos profit from that.");

coldStartGps();
}
pollStatistics();

if (is_neo6()) {
enableAlpIfDataIsAvailable();
}

if (mLastTimeTimeSet == 0) {
#ifdef UBX_M10
setMessageInterval(UBX_CFG_KEY_ID::CFG_MSGOUT_UBX_NAV_TIMEGPS_UART1, 1);
Expand Down Expand Up @@ -293,7 +342,6 @@ void Gps::softResetGps() {
log_i("Soft-RESET GPS!");
handle();
const uint8_t UBX_CFG_RST[] = {0x00, 0x00, 0x02, 0x00}; // WARM START
// const uint8_t UBX_CFG_RST[] = {0xFF, 0xFF, 0x02, 0x00}; // Cold START
// we had the case where the reset took several seconds
// see https://github.com/openbikesensor/OpenBikeSensorFirmware/issues/309
// Newer firmware (like M10 and likely also M8) will not ack this
Expand All @@ -304,6 +352,20 @@ void Gps::softResetGps() {
log_i("Soft-RESET GPS! Done");
}

void Gps::coldStartGps() {
log_i("Cold-Start GPS!");
handle();
const uint8_t UBX_CFG_RST[] = {0xFF, 0xFF, 0x00, 0x00};
// we had the case where the reset took several seconds
// see https://github.com/openbikesensor/OpenBikeSensorFirmware/issues/309
// Newer firmware (like M10 and likely also M8) will not ack this
// message so we do not wait for the ACK
sendUbx(UBX_MSG::CFG_RST, UBX_CFG_RST, 4);
waitForData(1000);
handle();
log_i("Cold Start GPS! Done");
}

/* There had been changes for the satellites used for SBAS
* in europe since the firmware of our GPS module was built
* we configure the module to use the 2 satellites that are
Expand Down Expand Up @@ -344,11 +406,15 @@ void Gps::enableAlpIfDataIsAvailable() {
/* Poll or refresh one time statistics, also spends some time
* to collect the results.
*/

void Gps::pollStatistics() {
handle();
sendUbx(UBX_MSG::AID_ALP);
handle();
sendUbx(UBX_MSG::MON_VER);
handle(20);
if (is_neo6()){
// AID_ALP is a neo6-only thing
sendUbx(UBX_MSG::AID_ALP);
}
handle();
sendUbx(UBX_MSG::MON_HW);
handle();
Expand Down Expand Up @@ -777,22 +843,32 @@ int32_t Gps::getMessagesWithFailedCrcCount() const {
}

void Gps::showWaitStatus(DisplayDevice const * display) const {
String satellitesString[2];
static bool clear = false;
if (!is_neo6() && !clear) {
obsDisplay->clear();
clear = true;
}
String satellitesString[3];
if (mValidMessagesReceived == 0) { // could not get any valid char from GPS module
satellitesString[0] = "OFF?";
} else if (mLastTimeTimeSet == 0) {
satellitesString[0] = String(mCurrentGpsRecord.mSatellitesUsed) + "sats SN:" + String(mLastNoiseLevel);
satellitesString[0] = "aGain:" + String(mLastGain);
satellitesString[1] = String(mCurrentGpsRecord.mSatellitesUsed) + "sats SN:" + String(mLastNoiseLevel);
} else {
satellitesString[0] = "GPS " + TimeUtils::timeToString();
satellitesString[0] = String(hw()).substring(1) + TimeUtils::timeToString();
satellitesString[1] = String(mCurrentGpsRecord.mSatellitesUsed) + "sats SN:" + String(mLastNoiseLevel);
}
satellitesString[2] = String(mCurrentGpsRecord.mFixStatus) + "<fx m>" + String(mValidMessagesReceived);

if (satellitesString[1].isEmpty()) {
obsDisplay->showTextOnGrid(2, display->currentLine(), satellitesString[0]);
} else {
obsDisplay->showTextOnGrid(2, display->currentLine() - 1, satellitesString[0]);
obsDisplay->showTextOnGrid(2, display->currentLine(), satellitesString[1]);
}
if (!is_neo6()){
obsDisplay->showTextOnGrid(0, 1, String(hw())+" Detail");
obsDisplay->showTextOnGrid(0, 2, "Gain:" + String(mLastGain) + " Jam:" + String(mLastJamInd));
obsDisplay->showTextOnGrid(0, 3, satellitesString[2]);
obsDisplay->showTextOnGrid(0, 4, String(mCurrentGpsRecord.mLatitude));
obsDisplay->showTextOnGrid(0, 5, String(mCurrentGpsRecord.mLongitude));
}
}

bool Gps::moduleIsAlive() const {
Expand Down Expand Up @@ -1098,12 +1174,25 @@ void Gps::parseUbxMessage() {
String(mGpsBuffer.monVer.swVersion).c_str(),
String(mGpsBuffer.monVer.hwVersion).c_str(),
mGpsBuffer.ubxHeader.length);
for (int i = 0; i < sizeof(hwString) && i < sizeof(mGpsBuffer.monVer.hwVersion) ; i++) {
hwString[i]=mGpsBuffer.monVer.hwVersion[i];
}
}
break;
case (uint16_t) UBX_MSG::MON_HW: {
log_v("MON-HW Antenna Status %d, noise level %d", mGpsBuffer.monHw.aStatus,
mGpsBuffer.monHw.noisePerMs);
const char* aStatus;
switch (mGpsBuffer.monHw.aStatus) {
case mGpsBuffer.monHw.INIT: aStatus = "init"; break;
case mGpsBuffer.monHw.DONTKNOW: aStatus = "?"; break;
case mGpsBuffer.monHw.OK: aStatus = "ok"; break;
case mGpsBuffer.monHw.SHORT: aStatus = "short"; break;
case mGpsBuffer.monHw.OPEN: aStatus = "open"; break;
default: aStatus = "invalid";
}
log_d("MON-HW Antenna Status %d %s, Antenna Power %d, Gain (0-8191) %d, noise level %d", mGpsBuffer.monHw.aStatus, aStatus, mGpsBuffer.monHw.aPower, mGpsBuffer.monHw.agcCnt, mGpsBuffer.monHw.noisePerMs);
mLastNoiseLevel = mGpsBuffer.monHw.noisePerMs;
mLastGain = mGpsBuffer.monHw.agcCnt;
mLastJamInd = mGpsBuffer.monHw.jamInd;
}
break;
case (uint16_t) UBX_MSG::NAV_STATUS: {
Expand All @@ -1113,7 +1202,7 @@ void Gps::parseUbxMessage() {
mGpsUptime = mGpsBuffer.navStatus.msss;
if (mGpsBuffer.navStatus.ttff != 0) {
addStatisticsMessage("TimeToFix: " + String(mGpsBuffer.navStatus.ttff) + "ms");
} else if (!mAidIniSent) {
} else if (!mAidIniSent and is_neo6()) {
mAidIniSent = true;
aidIni();
}
Expand All @@ -1130,7 +1219,7 @@ void Gps::parseUbxMessage() {
}
break;
case (uint16_t) UBX_MSG::NAV_SOL: {
log_v("SOL: iTOW: %u, gpsFix: %d, flags: %02x, numSV: %d, pDop: %04d.",
log_d("SOL: iTOW: %u, gpsFix: %d, flags: %02x, numSV: %d, pDop: %04d.",
mGpsBuffer.navSol.iTow, mGpsBuffer.navSol.gpsFix, mGpsBuffer.navSol.flags,
mGpsBuffer.navSol.numSv, mGpsBuffer.navSol.pDop);
if (mGpsBuffer.navSol.flags & 4) { // WKNSET
Expand All @@ -1148,15 +1237,15 @@ void Gps::parseUbxMessage() {
}
break;
case (uint16_t) UBX_MSG::NAV_PVT: {
log_v("PVT: iTOW: %u, fixType: %d, flags: %02x, numSV: %d, pDop: %04d.",
log_d("PVT: iTOW: %u, fixType: %d, flags: %02x, numSV: %d, pDop: %04d.",
mGpsBuffer.navPvt.iTow, mGpsBuffer.navPvt.fixType, mGpsBuffer.navPvt.flags,
mGpsBuffer.navPvt.numSV, mGpsBuffer.navPvt.pDOP);
prepareGpsData(mGpsBuffer.navPvt.iTow, mMessageStarted);
mIncomingGpsRecord.setInfo(mGpsBuffer.navPvt.numSV, mGpsBuffer.navPvt.fixType, mGpsBuffer.navPvt.flags);
}
break;
case (uint16_t) UBX_MSG::NAV_VELNED: {
log_v("VELNED: iTOW: %u, speed: %d cm/s, gSpeed: %d cm/s, heading: %d,"
log_d("VELNED: iTOW: %u, speed: %d cm/s, gSpeed: %d cm/s, heading: %d,"
" speedAcc: %d, cAcc: %d",
mGpsBuffer.navVelned.iTow, mGpsBuffer.navVelned.speed, mGpsBuffer.navVelned.gSpeed,
mGpsBuffer.navVelned.heading, mGpsBuffer.navVelned.sAcc, mGpsBuffer.navVelned.cAcc);
Expand Down Expand Up @@ -1289,7 +1378,7 @@ void Gps::parseUbxMessage() {
log_d("CFG_GNSS");
break;
default:
log_e("Got UBX_MESSAGE! Id: 0x%04x Len %d iTOW %d", mGpsBuffer.ubxHeader.ubxMsgId,
log_e("Got unparsed UBX_MESSAGE! Id: 0x%04x Len %d iTOW %d", mGpsBuffer.ubxHeader.ubxMsgId,
mGpsBuffer.ubxHeader.length, mGpsBuffer.navStatus.iTow);
}
}
Expand All @@ -1314,10 +1403,10 @@ void Gps::handleUbxNavTimeGps(const GpsBuffer::UbxNavTimeGps &message, const uin
mIncomingGpsRecord.setWeek(mLastGpsWeek);
}
if ((message.valid & 0x03) == 0x03 // WEEK && TOW
&& delayMs < 250
&& delayMs < 1000
&& message.tAcc < (20 * 1000 * 1000 /* 20ms */)
&& (mLastTimeTimeSet == 0
|| (mLastTimeTimeSet + (2 * 60 * 1000 /* 2 minutes */)) < receivedMs)) {
&& ((mLastTimeTimeSet == 0)
|| ((mLastTimeTimeSet + (2 * 60 * 1000 /* 2 minutes */)) < receivedMs))) {
String oldTime = TimeUtils::dateTimeToString();
TimeUtils::setClockByGps(message.iTow, message.fTow, message.week);
String newTime = TimeUtils::dateTimeToString();
Expand All @@ -1328,10 +1417,12 @@ void Gps::handleUbxNavTimeGps(const GpsBuffer::UbxNavTimeGps &message, const uin
+ "ms. tAcc:" + String(message.tAcc) + "ns");
}
if (mLastTimeTimeSet == 0) {
mLastTimeTimeSet = receivedMs;
// This triggers another NAV-TIMEGPS message!
if (delayMs < 100) { // keep mLastTimeTimeSet at 0 unless reasonable delayMs
mLastTimeTimeSet = receivedMs;
}
// This triggers another NAV-TIMEGPS message! more often until good time is received
#ifdef UBX_M6
setMessageInterval(UBX_MSG::NAV_TIMEGPS, 240, false); // every 4 minutes
setMessageInterval(UBX_MSG::NAV_TIMEGPS, (delayMs>100) ? 5 : 240, false); // every 4 minutes
#endif
#ifdef UBX_M10
setMessageInterval(UBX_CFG_KEY_ID::CFG_MSGOUT_UBX_NAV_TIMEGPS_UART1, 240, false); // every 4 minutes
Expand Down Expand Up @@ -1411,6 +1502,14 @@ uint16_t Gps::getLastNoiseLevel() const {
return mLastNoiseLevel;
}

uint16_t Gps::getLastAntennaGain() const {
return mLastGain;
}

uint8_t Gps::getLastJamInd() const {
return mLastJamInd;
}

uint32_t Gps::getBaudRate() {
return mSerial.baudRate();
}
Expand Down
Loading