AssistNow_Online Example1 is working nicely!

TO DO:
Overload (?) pushAssistNowData so it can accept uint8_t * as the data source, instead of a String.
This commit is contained in:
PaulZC
2021-11-25 20:31:44 +00:00
parent 28e7c12b32
commit 19ff31b8b7
3 changed files with 111 additions and 50 deletions
@@ -6,7 +6,7 @@
basically do whatever you want with this code. basically do whatever you want with this code.
This example shows how to obtain AssistNow Online data from u-blox Thingstream over WiFi This example shows how to obtain AssistNow Online data from u-blox Thingstream over WiFi
and push it over I2C to a ZED-F9x. and push it over I2C to a u-blox module.
You will need to have a token to be able to access Thingstream. See the AssistNow README for more details. You will need to have a token to be able to access Thingstream. See the AssistNow README for more details.
@@ -14,11 +14,14 @@
- WiFi credentials - WiFi credentials
- AssistNow token string - AssistNow token string
Uncomment the "#define USE_MGA_ACKs" below to test the more robust method of using the
UBX_MGA_ACK_DATA0 acknowledgements to confirm that each MGA message has been accepted.
Feel like supporting open source hardware? Feel like supporting open source hardware?
Buy a board from SparkFun! Buy a board from SparkFun!
SparkFun Thing Plus - ESP32 WROOM: https://www.sparkfun.com/products/15663 SparkFun Thing Plus - ESP32 WROOM: https://www.sparkfun.com/products/15663
ZED-F9P RTK2: https://www.sparkfun.com/products/16481 ZED-F9P RTK2: https://www.sparkfun.com/products/16481
SparkFun GPS Breakout - ZOE-M8Q (Qwiic): https://www.sparkfun.com/products/15193 SparkFun GPS Breakout - ZOE-M8Q (Qwiic): https://www.sparkfun.com/products/15193
Hardware Connections: Hardware Connections:
Plug a Qwiic cable into the GNSS and a ESP32 Thing Plus Plug a Qwiic cable into the GNSS and a ESP32 Thing Plus
@@ -26,6 +29,8 @@
Open the serial monitor at 115200 baud to see the output Open the serial monitor at 115200 baud to see the output
*/ */
//#define USE_MGA_ACKs // Uncomment this line to use the UBX_MGA_ACK_DATA0 acknowledgements
#include <WiFi.h> #include <WiFi.h>
#include <HTTPClient.h> #include <HTTPClient.h>
#include "secrets.h" #include "secrets.h"
@@ -67,8 +72,6 @@ void setup()
myGNSS.setI2COutput(COM_TYPE_UBX); //Turn off NMEA noise myGNSS.setI2COutput(COM_TYPE_UBX); //Turn off NMEA noise
myGNSS.setNavigationFrequency(1); //Set output in Hz.
//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
// Connect to WiFi. // Connect to WiFi.
@@ -91,7 +94,8 @@ void setup()
int payloadSize = 0; // This will be updated with the length of the data we get from the server int payloadSize = 0; // This will be updated with the length of the data we get from the server
String payload; // This will store the data we get from the server String payload; // This will store the data we get from the server
// Assemble the URL. Note the slash after assistNowServer // Assemble the URL
// Note the slash after the first %s (assistNowServer)
snprintf(theURL, URL_BUFFER_SIZE, "%s/%s%s%s%s%s%s", snprintf(theURL, URL_BUFFER_SIZE, "%s/%s%s%s%s%s%s",
assistNowServer, assistNowServer,
getQuery, getQuery,
@@ -114,18 +118,18 @@ void setup()
if(httpCode > 0) if(httpCode > 0)
{ {
// HTTP header has been sent and Server response header has been handled // HTTP header has been sent and Server response header has been handled
Serial.printf("[HTTP] GET... code: %d\n", httpCode); Serial.printf("[HTTP] GET... code: %d\r\n", httpCode);
// If the GET was successful, read the data // If the GET was successful, read the data
if(httpCode == HTTP_CODE_OK) // Code 200 if(httpCode == HTTP_CODE_OK) // Check for code 200
{ {
payloadSize = http.getSize(); payloadSize = http.getSize();
Serial.printf("Server returned %d bytes\r\n", payloadSize); Serial.printf("Server returned %d bytes\r\n", payloadSize);
payload = http.getString(); // Get the payload payload = http.getString(); // Get the payload
// Pretty-print the payload as HEX // Pretty-print the payload as HEX
/* /*
int i; int i;
for(i = 0; i < payloadSize; i++) for(i = 0; i < payloadSize; i++)
{ {
@@ -143,7 +147,7 @@ void setup()
} }
else else
{ {
Serial.printf("[HTTP] GET... failed, error: %s\n", http.errorToString(httpCode).c_str()); Serial.printf("[HTTP] GET... failed, error: %s\r\n", http.errorToString(httpCode).c_str());
} }
http.end(); http.end();
@@ -152,12 +156,40 @@ void setup()
// Push the AssistNow data to the module // Push the AssistNow data to the module
if (payloadSize > 0) if (payloadSize > 0)
{ {
// Enable the 'major' debug messages on Serial so we can see what AssistNow data is being sent // Enable the 'major' debug messages on Serial so we can see what AssistNow data is being sent
myGNSS.enableDebugging(Serial, true); myGNSS.enableDebugging(Serial, true);
// Push all the AssistNow data - without checking for UBX-MGA-ACK messages #ifndef USE_MGA_ACKs
myGNSS.pushAssistNowData((uint8_t *)&payload, (size_t)payloadSize);
// ***** Don't use the UBX_MGA_ACK_DATA0 messages *****
// Push all the AssistNow data. Don't use UBX_MGA_ACK_DATA0's. Use the default delay of 7ms between messages.
myGNSS.pushAssistNowData(payload, (size_t)payloadSize);
#else
// ***** Use the UBX_MGA_ACK_DATA0 messages *****
// Tell the module to return UBX_MGA_ACK_DATA0 messages when we push the AssistNow data
myGNSS.setAckAiding(1);
// Speed things up by setting setI2CpollingWait to 1ms
myGNSS.setI2CpollingWait(1);
// Push all the AssistNow data.
// We have called setAckAiding(1) to instruct the module to return MGA-ACK messages.
// So, we could set the pushAssistNowData mgaAck parameter to SFE_UBLOX_MGA_ASSIST_ACK_YES.
// But, just for giggles, let's use SFE_UBLOX_MGA_ASSIST_ACK_ENQUIRE just to confirm that the
// MGA-ACK messages are actually enabled.
// Wait for up to 1000ms for each ACK to arrive! 1000ms is a bit excessive... 7ms is nearer the mark.
myGNSS.pushAssistNowData(payload, (size_t)payloadSize, SFE_UBLOX_MGA_ASSIST_ACK_ENQUIRE, 1000);
// Set setI2CpollingWait to 125ms to avoid pounding the I2C bus
myGNSS.setI2CpollingWait(125);
#endif
} }
} }
@@ -165,6 +197,8 @@ void setup()
void loop() void loop()
{ {
// Print the UBX-NAV-PVT data so we can see how quickly the fixType goes to 3D
long latitude = myGNSS.getLatitude(); long latitude = myGNSS.getLatitude();
Serial.print(F("Lat: ")); Serial.print(F("Lat: "));
Serial.print(latitude); Serial.print(latitude);
@@ -193,4 +227,4 @@ void loop()
else if(fixType == 5) Serial.print(F("Time only")); else if(fixType == 5) Serial.print(F("Time only"));
Serial.println(); Serial.println();
} }
+58 -31
View File
@@ -1075,6 +1075,11 @@ bool SFE_UBLOX_GNSS::checkAutomatic(uint8_t Class, uint8_t ID)
} }
} }
break; break;
case UBX_CLASS_MGA:
{
if (packetUBXMGAACK != NULL) result = true;
}
break;
case UBX_CLASS_HNR: case UBX_CLASS_HNR:
{ {
switch (ID) switch (ID)
@@ -1205,6 +1210,11 @@ uint16_t SFE_UBLOX_GNSS::getMaxPayloadSize(uint8_t Class, uint8_t ID)
} }
} }
break; break;
case UBX_CLASS_MGA:
{
maxSize = UBX_MGA_ACK_DATA0_LEN;
}
break;
case UBX_CLASS_HNR: case UBX_CLASS_HNR:
{ {
switch (ID) switch (ID)
@@ -3973,7 +3983,7 @@ bool SFE_UBLOX_GNSS::pushRawData(uint8_t *dataBytes, size_t numDataBytes, bool s
// Check for UBX-MGA-ACK responses if required (if mgaAck is YES or ENQUIRE) // Check for UBX-MGA-ACK responses if required (if mgaAck is YES or ENQUIRE)
// Wait for maxWait millis after sending each packet (if mgaAck is NO) // Wait for maxWait millis after sending each packet (if mgaAck is NO)
// Return how many MGA packets were pushed successfully // Return how many MGA packets were pushed successfully
uint16_t SFE_UBLOX_GNSS::pushAssistNowData(uint8_t *dataBytes, size_t numDataBytes, sfe_ublox_mga_assist_ack_e mgaAck, uint16_t maxWait) uint16_t SFE_UBLOX_GNSS::pushAssistNowData(String dataBytes, size_t numDataBytes, sfe_ublox_mga_assist_ack_e mgaAck, uint16_t maxWait)
{ {
size_t dataPtr = 0; // Pointer into dataBytes size_t dataPtr = 0; // Pointer into dataBytes
uint16_t packetsProcessed = 0; // Keep count of how many packets have been processed uint16_t packetsProcessed = 0; // Keep count of how many packets have been processed
@@ -3986,9 +3996,15 @@ uint16_t SFE_UBLOX_GNSS::pushAssistNowData(uint8_t *dataBytes, size_t numDataByt
uint8_t ackAiding = getAckAiding(maxWait); // Enquire if we should expect Acks uint8_t ackAiding = getAckAiding(maxWait); // Enquire if we should expect Acks
if (ackAiding == 1) if (ackAiding == 1)
checkForAcks = true; checkForAcks = true;
if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging
{
_debugSerial->print(F("pushAssistNowData: mgaAck is ENQUIRE. getAckAiding returned "));
_debugSerial->println(ackAiding);
}
} }
// If checkForAcks is true, then we need to set up storage for the UBX-MGA-ACK-DATA0 messages and use the callback // If checkForAcks is true, then we need to set up storage for the UBX-MGA-ACK-DATA0 messages
if (checkForAcks) if (checkForAcks)
{ {
if (packetUBXMGAACK == NULL) initPacketUBXMGAACK(); //Check that RAM has been allocated for the MGA_ACK data if (packetUBXMGAACK == NULL) initPacketUBXMGAACK(); //Check that RAM has been allocated for the MGA_ACK data
@@ -4001,31 +4017,43 @@ uint16_t SFE_UBLOX_GNSS::pushAssistNowData(uint8_t *dataBytes, size_t numDataByt
// Start by checking the validity of the packet being pointed to // Start by checking the validity of the packet being pointed to
bool dataIsOK = true; bool dataIsOK = true;
dataIsOK &= dataBytes[dataPtr + 0] == UBX_SYNCH_1; // Check for 0xB5 dataIsOK &= (dataBytes[dataPtr + 0] == UBX_SYNCH_1); // Check for 0xB5
dataIsOK &= dataBytes[dataPtr + 1] == UBX_SYNCH_2; // Check for 0x62 dataIsOK &= (dataBytes[dataPtr + 1] == UBX_SYNCH_2); // Check for 0x62
dataIsOK &= dataBytes[dataPtr + 2] == UBX_CLASS_MGA; // Check for class UBX-MGA dataIsOK &= (dataBytes[dataPtr + 2] == UBX_CLASS_MGA); // Check for class UBX-MGA
size_t packetLength = (size_t)dataBytes[dataPtr + 4] + ((size_t)dataBytes[dataPtr + 5] << 8); // Extract the length size_t packetLength = ((size_t)dataBytes[dataPtr + 4]) | (((size_t)dataBytes[dataPtr + 5]) << 8); // Extract the length
uint8_t checksumA = 0; uint8_t checksumA = 0;
uint8_t checksumB = 0; uint8_t checksumB = 0;
// Calculate the checksum bytes // Calculate the checksum bytes
// Keep going until the end of the packet is reached (payloadPtr == (dataPtr + packetLength)) // Keep going until the end of the packet is reached (payloadPtr == (dataPtr + packetLength))
// or we reach the end of the AssistNow data (payloadPtr == numDataBytes) // or we reach the end of the AssistNow data (payloadPtr == numDataBytes)
for (size_t payloadPtr = dataPtr + ((size_t)6); (payloadPtr < (dataPtr + packetLength + ((size_t)6))) && (payloadPtr < numDataBytes); payloadPtr++) for (size_t payloadPtr = dataPtr + ((size_t)2); (payloadPtr < (dataPtr + packetLength + ((size_t)6))) && (payloadPtr < numDataBytes); payloadPtr++)
{ {
checksumA += dataBytes[payloadPtr]; checksumA += dataBytes[payloadPtr];
checksumB += checksumA; checksumB += checksumA;
} }
// Check the checksum bytes // Check the checksum bytes
dataIsOK &= checksumA == dataBytes[dataPtr + packetLength + ((size_t)6)]; dataIsOK &= (checksumA == dataBytes[dataPtr + packetLength + ((size_t)6)]);
dataIsOK &= checksumB == dataBytes[dataPtr + packetLength + ((size_t)7)]; dataIsOK &= (checksumB == dataBytes[dataPtr + packetLength + ((size_t)7)]);
dataIsOK &= (dataPtr + packetLength + ((size_t)8)) <= numDataBytes; // Check we haven't overrun
dataIsOK &= ((dataPtr + packetLength + ((size_t)8)) <= numDataBytes); // Check we haven't overrun
// If the data is valid, push it // If the data is valid, push it
if (dataIsOK) if (dataIsOK)
{ {
pushRawData((uint8_t *)&dataBytes[dataPtr], packetLength + ((size_t)8)); // Push the data pushRawData((uint8_t *)&dataBytes[dataPtr], packetLength + ((size_t)8)); // Push the data
if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging
{
_debugSerial->print(F("pushAssistNowData: packet ID 0x"));
if (dataBytes[dataPtr + 3] < 0x10)
_debugSerial->print(F("0"));
_debugSerial->print(dataBytes[dataPtr + 3], HEX);
_debugSerial->print(F(" length "));
_debugSerial->println(packetLength);
}
if (checkForAcks) if (checkForAcks)
{ {
unsigned long startTime = millis(); unsigned long startTime = millis();
@@ -4036,26 +4064,21 @@ uint16_t SFE_UBLOX_GNSS::pushAssistNowData(uint8_t *dataBytes, size_t numDataByt
if (packetUBXMGAACK->head != packetUBXMGAACK->tail) // Does the MGA ACK ringbuffer contain any ACK's? if (packetUBXMGAACK->head != packetUBXMGAACK->tail) // Does the MGA ACK ringbuffer contain any ACK's?
{ {
bool dataAckd = true; // Check if we've received the correct ACK bool dataAckd = true; // Check if we've received the correct ACK
dataAckd &= packetUBXMGAACK->data[packetUBXMGAACK->tail].msgId == dataBytes[dataPtr + 3]; dataAckd &= (packetUBXMGAACK->data[packetUBXMGAACK->tail].msgId == dataBytes[dataPtr + 3]); // Check if the message ID matches
dataAckd &= packetUBXMGAACK->data[packetUBXMGAACK->tail].msgPayloadStart[0] == dataBytes[dataPtr + 6]; dataAckd &= (packetUBXMGAACK->data[packetUBXMGAACK->tail].msgPayloadStart[0] == dataBytes[dataPtr + 6]); // Check if the first four data bytes match
dataAckd &= packetUBXMGAACK->data[packetUBXMGAACK->tail].msgPayloadStart[1] == dataBytes[dataPtr + 7]; dataAckd &= (packetUBXMGAACK->data[packetUBXMGAACK->tail].msgPayloadStart[1] == dataBytes[dataPtr + 7]);
dataAckd &= packetUBXMGAACK->data[packetUBXMGAACK->tail].msgPayloadStart[2] == dataBytes[dataPtr + 8]; dataAckd &= (packetUBXMGAACK->data[packetUBXMGAACK->tail].msgPayloadStart[2] == dataBytes[dataPtr + 8]);
dataAckd &= packetUBXMGAACK->data[packetUBXMGAACK->tail].msgPayloadStart[3] == dataBytes[dataPtr + 9]; dataAckd &= (packetUBXMGAACK->data[packetUBXMGAACK->tail].msgPayloadStart[3] == dataBytes[dataPtr + 9]);
if (dataAckd) // Is this the ACK we are looking for? if (dataAckd) // Is this the ACK we are looking for?
{ {
if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging
{
_debugSerial->print(F("pushAssistNowData: packet ID 0x"));
if (dataBytes[dataPtr + 3] < 0x10)
_debugSerial->print(F("0"));
_debugSerial->print(dataBytes[dataPtr + 3], HEX);
}
if ((packetUBXMGAACK->data[packetUBXMGAACK->tail].type == (uint8_t)1) && (packetUBXMGAACK->data[packetUBXMGAACK->tail].infoCode == (uint8_t)SFE_UBLOX_MGA_ACK_INFOCODE_ACCEPTED)) if ((packetUBXMGAACK->data[packetUBXMGAACK->tail].type == (uint8_t)1) && (packetUBXMGAACK->data[packetUBXMGAACK->tail].infoCode == (uint8_t)SFE_UBLOX_MGA_ACK_INFOCODE_ACCEPTED))
{ {
if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging
{ {
_debugSerial->println(F(" was accepted")); _debugSerial->print(F("pushAssistNowData: packet was accepted after "));
_debugSerial->print(millis() - startTime);
_debugSerial->println(F(" ms"));
} }
packetsProcessed++; packetsProcessed++;
} }
@@ -4063,7 +4086,7 @@ uint16_t SFE_UBLOX_GNSS::pushAssistNowData(uint8_t *dataBytes, size_t numDataByt
{ {
if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging
{ {
_debugSerial->print(F(" was _not_ accepted. infoCode is ")); _debugSerial->print(F("pushAssistNowData: packet was _not_ accepted. infoCode is "));
_debugSerial->println(packetUBXMGAACK->data[packetUBXMGAACK->tail].infoCode); _debugSerial->println(packetUBXMGAACK->data[packetUBXMGAACK->tail].infoCode);
} }
} }
@@ -4079,16 +4102,14 @@ uint16_t SFE_UBLOX_GNSS::pushAssistNowData(uint8_t *dataBytes, size_t numDataByt
{ {
if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging
{ {
_debugSerial->print(F("pushAssistNowData: packet ID 0x")); _debugSerial->println(F("pushAssistNowData: packet ack timed out!"));
if (dataBytes[dataPtr + 3] < 0x10)
_debugSerial->print(F("0"));
_debugSerial->print(dataBytes[dataPtr + 3], HEX);
_debugSerial->println(F(" timed out!"));
} }
} }
} }
else else
{ {
// We are not checking for Acks, so let's assume the send was successful?
packetsProcessed++;
// We are not checking for Acks, so delay for maxWait millis unless we've reached the end of the data // We are not checking for Acks, so delay for maxWait millis unless we've reached the end of the data
if ((dataPtr + packetLength + ((size_t)8)) < numDataBytes) if ((dataPtr + packetLength + ((size_t)8)) < numDataBytes)
{ {
@@ -4103,7 +4124,7 @@ uint16_t SFE_UBLOX_GNSS::pushAssistNowData(uint8_t *dataBytes, size_t numDataByt
// The data was invalid. Send a debug message and then try to find the next 0xB5 // The data was invalid. Send a debug message and then try to find the next 0xB5
if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging
{ {
_debugSerial->print(F("pushAssistNowData: bad data - ignored! dataPtr is")); _debugSerial->print(F("pushAssistNowData: bad data - ignored! dataPtr is "));
_debugSerial->println(dataPtr); _debugSerial->println(dataPtr);
} }
@@ -4114,6 +4135,12 @@ uint16_t SFE_UBLOX_GNSS::pushAssistNowData(uint8_t *dataBytes, size_t numDataByt
} }
} }
if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging
{
_debugSerial->print(F("pushAssistNowData: packetsProcessed: "));
_debugSerial->println(packetsProcessed);
}
return (packetsProcessed); return (packetsProcessed);
} }
@@ -5615,7 +5642,7 @@ bool SFE_UBLOX_GNSS::setAckAiding(uint8_t ackAiding, uint16_t maxWait) // Set th
// There are three versions of UBX-CFG-NAVX5 but the ackAid flag is always in bit 10 of mask1 // There are three versions of UBX-CFG-NAVX5 but the ackAid flag is always in bit 10 of mask1
payloadCfg[2] = 0x00; // Clear the LS byte of mask1 payloadCfg[2] = 0x00; // Clear the LS byte of mask1
payloadCfg[3] = 0x40; // Set _only_ the ackAid flag = bit 10 of mask1 = bit 2 of the MS byte payloadCfg[3] = 0x04; // Set _only_ the ackAid flag = bit 10 of mask1 = bit 2 of the MS byte
payloadCfg[4] = 0x00; // Clear the LS byte of mask2, just in case payloadCfg[4] = 0x00; // Clear the LS byte of mask2, just in case
payloadCfg[5] = 0x00; // Clear the LS byte of mask2, just in case payloadCfg[5] = 0x00; // Clear the LS byte of mask2, just in case
+2 -2
View File
@@ -708,8 +708,8 @@ public:
// Check for UBX-MGA-ACK responses if required (if mgaAck is YES or ENQUIRE) // Check for UBX-MGA-ACK responses if required (if mgaAck is YES or ENQUIRE)
// Wait for maxWait millis after sending each packet (if mgaAck is NO) // Wait for maxWait millis after sending each packet (if mgaAck is NO)
// Return how many MGA packets were pushed successfully // Return how many MGA packets were pushed successfully
#define defaultMGAdelay 10 // Default to waiting for 10ms between each MGA message #define defaultMGAdelay 7 // Default to waiting for 7ms between each MGA message
uint16_t pushAssistNowData(uint8_t *dataBytes, size_t numDataBytes, sfe_ublox_mga_assist_ack_e mgaAck = SFE_UBLOX_MGA_ASSIST_ACK_NO, uint16_t maxWait = defaultMGAdelay); uint16_t pushAssistNowData(String dataBytes, size_t numDataBytes, sfe_ublox_mga_assist_ack_e mgaAck = SFE_UBLOX_MGA_ASSIST_ACK_NO, uint16_t maxWait = defaultMGAdelay);
// Support for data logging // Support for data logging
void setFileBufferSize(uint16_t bufferSize); // Set the size of the file buffer. This must be called _before_ .begin. void setFileBufferSize(uint16_t bufferSize); // Set the size of the file buffer. This must be called _before_ .begin.