diff --git a/examples/AssistNow/AssistNow_Online/Example3_AssistNowOnline_PositionAssist/Example3_AssistNowOnline_PositionAssist.ino b/examples/AssistNow/AssistNow_Online/Example3_AssistNowOnline_PositionAssist/Example3_AssistNowOnline_PositionAssist.ino new file mode 100644 index 0000000..75ba417 --- /dev/null +++ b/examples/AssistNow/AssistNow_Online/Example3_AssistNowOnline_PositionAssist/Example3_AssistNowOnline_PositionAssist.ino @@ -0,0 +1,299 @@ +/* + Use ESP32 WiFi to get AssistNow Online data from u-blox Thingstream + By: SparkFun Electronics / Paul Clark + Date: November 24th, 2021 + License: MIT. See license file for more information but you can + basically do whatever you want with this code. + + This example shows how to obtain AssistNow Online data from u-blox Thingstream over WiFi + and push it over I2C to a u-blox module. + + This example shows how to provide initial position assistance. Uncomment #define USE_SERVER_ASSISTANCE + below to include the position in the AssistNow data request, instead of using setPositionAssistanceLLH. + + You will need to have a token to be able to access Thingstream. See the AssistNow README for more details. + + Update secrets.h with your: + - WiFi credentials + - AssistNow token string + + Feel like supporting open source hardware? + Buy a board from SparkFun! + SparkFun Thing Plus - ESP32 WROOM: https://www.sparkfun.com/products/15663 + ZED-F9P RTK2: https://www.sparkfun.com/products/16481 + SparkFun GPS Breakout - ZOE-M8Q (Qwiic): https://www.sparkfun.com/products/15193 + + Hardware Connections: + Plug a Qwiic cable into the GNSS and a ESP32 Thing Plus + If you don't have a platform with a Qwiic connection use the SparkFun Qwiic Breadboard Jumper (https://www.sparkfun.com/products/14425) + Open the serial monitor at 115200 baud to see the output +*/ + +//#define USE_SERVER_ASSISTANCE // Uncomment this line to include the position in the AssistNow data request + +#include +#include +#include "secrets.h" + +const char assistNowServer[] = "https://online-live1.services.u-blox.com"; +//const char assistNowServer[] = "https://online-live2.services.u-blox.com"; // Alternate server + +const char getQuery[] = "GetOnlineData.ashx?"; +const char tokenPrefix[] = "token="; +const char tokenSuffix[] = ";"; +const char getGNSS[] = "gnss=gps,glo;"; // GNSS can be: gps,qzss,glo,bds,gal +const char getDataType[] = "datatype=eph,alm,aux;"; // Data type can be: eph,alm,aux,pos + +#ifdef USE_SERVER_ASSISTANCE +const char useLatitude[] = "lat=55.0;"; // Use an approximate latitude of 55 degrees north. Replace this with your latitude. +const char useLongitude[] = "lon=-1.0;"; // Use an approximate longitude of 1 degree west. Replace this with your longitude. +const char useAlt[] = "alt=100;"; // Use an approximate latitude of 100m above WGS84. Replace this with your altitude. +const char usePosAcc[] = "pacc=100000;"; // Use a position accuracy of 100000m (100km) +#endif + +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +#include //http://librarymanager/All#SparkFun_u-blox_GNSS +SFE_UBLOX_GNSS myGNSS; + +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +#include "time.h" + +const char* ntpServer = "pool.ntp.org"; // The Network Time Protocol Server + +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +void setup() +{ + delay(1000); + + Serial.begin(115200); + Serial.println(F("AssistNow Example")); + + while (Serial.available()) Serial.read(); // Empty the serial buffer + Serial.println(F("Press any key to begin...")); + while (!Serial.available()); // Wait for a keypress + + //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + // Start I2C. Connect to the GNSS. + + Wire.begin(); //Start I2C + + if (myGNSS.begin() == false) //Connect to the Ublox module using Wire port + { + Serial.println(F("u-blox GPS not detected at default I2C address. Please check wiring. Freezing.")); + while (1); + } + Serial.println(F("u-blox module connected")); + + myGNSS.setI2COutput(COM_TYPE_UBX); //Turn off NMEA noise + + //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + // Connect to WiFi. + + Serial.print(F("Connecting to local WiFi")); + + WiFi.begin(ssid, password); + while (WiFi.status() != WL_CONNECTED) + { + delay(500); + Serial.print(F(".")); + } + Serial.println(); + + Serial.println(F("WiFi connected!")); + + //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + // Set the RTC using network time. (Code taken from the SimpleTime example.) + + // Request the time from the NTP server and use it to set the ESP32's RTC. + configTime(0, 0, ntpServer); // Set the GMT and daylight offsets to zero. We need UTC, not local time. + + struct tm timeinfo; + if(!getLocalTime(&timeinfo)) + { + Serial.println("Failed to obtain time"); + } + else + { + Serial.println(&timeinfo, "Time is: %A, %B %d %Y %H:%M:%S"); + } + + //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + // Use HTTP GET to receive the AssistNow_Online data + + const int URL_BUFFER_SIZE = 256; + char theURL[URL_BUFFER_SIZE]; // This will contain the HTTP URL + 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 + + // Assemble the URL + // Note the slash after the first %s (assistNowServer) +#ifdef USE_SERVER_ASSISTANCE + snprintf(theURL, URL_BUFFER_SIZE, "%s/%s%s%s%s%s%s%s%s%s%s", + assistNowServer, + getQuery, + tokenPrefix, + myAssistNowToken, + tokenSuffix, + getGNSS, + getDataType, + useLatitude, + useLongitude, + useAlt, + usePosAcc); +#else + snprintf(theURL, URL_BUFFER_SIZE, "%s/%s%s%s%s%s%s", + assistNowServer, + getQuery, + tokenPrefix, + myAssistNowToken, + tokenSuffix, + getGNSS, + getDataType); +#endif + + Serial.print(F("HTTP URL is: ")); + Serial.println(theURL); + + HTTPClient http; + + http.begin(theURL); + + int httpCode = http.GET(); // HTTP GET + + // httpCode will be negative on error + if(httpCode > 0) + { + // HTTP header has been sent and Server response header has been handled + Serial.printf("[HTTP] GET... code: %d\r\n", httpCode); + + // If the GET was successful, read the data + if(httpCode == HTTP_CODE_OK) // Check for code 200 + { + payloadSize = http.getSize(); + Serial.printf("Server returned %d bytes\r\n", payloadSize); + + payload = http.getString(); // Get the payload + + // Pretty-print the payload as HEX + /* + int i; + for(i = 0; i < payloadSize; i++) + { + if (payload[i] < 0x10) // Print leading zero + Serial.print("0"); + Serial.print(payload[i], HEX); + Serial.print(" "); + if ((i % 16) == 15) + Serial.println(); + } + if ((i % 16) != 15) + Serial.println(); + */ + } + } + else + { + Serial.printf("[HTTP] GET... failed, error: %s\r\n", http.errorToString(httpCode).c_str()); + } + + http.end(); + + //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + // Speed things up by setting setI2CpollingWait to 1ms + myGNSS.setI2CpollingWait(1); + + //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + // Tell the module to return UBX_MGA_ACK_DATA0 messages when we push the AssistNow data + myGNSS.setAckAiding(1); + + //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + // Push the RTC time to the module + + // Uncomment the next line to enable the 'major' debug messages on Serial so you can see what AssistNow data is being sent + //myGNSS.enableDebugging(Serial, true); + + if(getLocalTime(&timeinfo)) + { + // Provide time assistance. Use the UBX_MGA_ACK_DATA0 acknowledgements. Set tAccS to 2 seconds. + myGNSS.setUTCTimeAssistance(timeinfo.tm_year + 1900, timeinfo.tm_mon + 1, timeinfo.tm_mday, + timeinfo.tm_hour, timeinfo.tm_min, timeinfo.tm_sec, 0, 2, 0, 0, SFE_UBLOX_MGA_ASSIST_ACK_YES, 100); + } + else + { + Serial.println("Failed to obtain time. This will not work well. The GNSS needs accurate time to start up quickly."); + } + + //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + // If desired - push initial position assistance to the module + +#ifndef USE_SERVER_ASSISTANCE + + // Use 55 degrees (*10^7) north, 1 degree (*10^7) west, 100m (10000cm) altitude, 100km (10000000cm) accuracy. Replace these with your position. + // The units for lat and lon are degrees * 1e-7 (WGS84) + // The units for alt (WGS84) and posAcc (stddev) are cm. + myGNSS.setPositionAssistanceLLH(550000000, -10000000, 10000, 10000000, SFE_UBLOX_MGA_ASSIST_ACK_YES, 100); + + // We could use setPositionAssistanceXYZ instead if needed. + +#endif + + //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + // Push the AssistNow data to the module - WITHOUT THE TIME + + if (payloadSize > 0) + { + // Push the AssistNow data. Use the UBX_MGA_ACK_DATA0 acknowledgements. + // The 'true' parameter tells pushAssistNowData not to push any time data from the payload. + myGNSS.pushAssistNowData(true, payload, (size_t)payloadSize, SFE_UBLOX_MGA_ASSIST_ACK_YES, 100); + } + + //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + // Disconnect the WiFi as it's no longer needed + + WiFi.disconnect(true); + WiFi.mode(WIFI_OFF); + Serial.println(F("WiFi disconnected")); + + //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + // Avoid pounding the I2C bus by setting setI2CpollingWait to 125ms + myGNSS.setI2CpollingWait(125); +} + +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +void loop() +{ + // Print the UBX-NAV-PVT data so we can see how quickly the fixType goes to 3D + + long latitude = myGNSS.getLatitude(); + Serial.print(F("Lat: ")); + Serial.print(latitude); + + long longitude = myGNSS.getLongitude(); + Serial.print(F(" Long: ")); + Serial.print(longitude); + Serial.print(F(" (degrees * 10^-7)")); + + long altitude = myGNSS.getAltitude(); + Serial.print(F(" Alt: ")); + Serial.print(altitude); + Serial.print(F(" (mm)")); + + byte SIV = myGNSS.getSIV(); + Serial.print(F(" SIV: ")); + Serial.print(SIV); + + byte fixType = myGNSS.getFixType(); + Serial.print(F(" Fix: ")); + if(fixType == 0) Serial.print(F("No fix")); + else if(fixType == 1) Serial.print(F("Dead reckoning")); + else if(fixType == 2) Serial.print(F("2D")); + else if(fixType == 3) Serial.print(F("3D")); + else if(fixType == 4) Serial.print(F("GNSS + Dead reckoning")); + else if(fixType == 5) Serial.print(F("Time only")); + + Serial.println(); +} diff --git a/examples/AssistNow/AssistNow_Online/Example3_AssistNowOnline_PositionAssist/secrets.h b/examples/AssistNow/AssistNow_Online/Example3_AssistNowOnline_PositionAssist/secrets.h new file mode 100644 index 0000000..4eb7a9c --- /dev/null +++ b/examples/AssistNow/AssistNow_Online/Example3_AssistNowOnline_PositionAssist/secrets.h @@ -0,0 +1,6 @@ +//Your WiFi credentials +const char ssid[] = "TRex"; +const char password[] = "hasBigTeeth"; + +//Your AssistNow token +const char myAssistNowToken[] = "58XXXXXXXXXXXXXXXXXXYQ"; diff --git a/examples/AssistNow/README.md b/examples/AssistNow/README.md index 6dc2471..cee89a9 100644 --- a/examples/AssistNow/README.md +++ b/examples/AssistNow/README.md @@ -10,7 +10,7 @@ With AssistNow Online, an Internet connected host downloads assistance data from Please see the [AssistNow_Online](./AssistNow_Online) examples for more details. These examples were written for the ESP32, but will run on other platforms too. -The new functions we've added to the library to support AssistNow Online are described [Code Support for AssistNow below](#Code-Support-for-AssistNow) +The new functions we've added to the library to support AssistNow Online are described [Code Support for AssistNow below](#Code-Support-for-AssistNow). ## AssistNowTM Offline @@ -20,7 +20,7 @@ Please see the [AssistNow_Offline](./AssistNow_Offline) examples for more detail **Note: AssistNow Offline is not supported by the ZED-F9P. "The ZED-F9P supports AssistNow Online only."** -The new functions we've added to the library to support AssistNow Offline are described [Code Support for AssistNow below](#Code-Support-for-AssistNow) +The new functions we've added to the library to support AssistNow Offline are described [Code Support for AssistNow below](#Code-Support-for-AssistNow). ## AssistNowTM Autonomous @@ -37,7 +37,7 @@ AssistNow Autonomous offers augmentation for up to 6 days. Please see the [AssistNow_Autonomous](./AssistNow_Autonomous) examples for more details. -The new functions we've added to the library to support AssistNow Autonomous are described [Code Support for AssistNow below](#Code-Support-for-AssistNow) +The new functions we've added to the library to support AssistNow Autonomous are described [Code Support for AssistNow below](#Code-Support-for-AssistNow). ## AssistNow Service Token @@ -124,6 +124,22 @@ Only the ```year```, ```month```, ```day```, ```hour```, ```minute``` and ```sec Call ```setUTCTimeAssistance``` _before_ ```pushAssistNowData```. +## Initial Position Assistance + +You can further decrease the time-to-first-fix by also providing the receiver's position - if known. There are two ways to do this: + +* The position can be specified when requesting AssistNow Online data from the server: + * include the key name ```lat``` with the approximate user latitude in WGS 84 expressed in degrees and fractional degrees. Must be in range -90 to 90. Example: ```lat=47.2;``` + * include the key name ```lon``` with the approximate user longitude in WGS 84 expressed in degrees and fractional degrees. Must be in range -180 to 180. Example: ```lon=8.55;``` + * include the key name ```alt``` with the approximate user altitude above WGS 84 Ellipsoid in meters. If this value is not provided, the server assumes an altitude of 0 meters. Must be in range -1000 to 50000 + * if possible, include the key name ```pacc``` with the approximate accuracy of submitted position in meters. If this value is not provided, the server assumes an accuracy of 300 km. Must be in range 0 to 6000000 + * the position assistance data will then be automatically included in the AssistNow Online data +* Provide initial position assistance data by calling one of: + * bool setPositionAssistanceXYZ(int32_t ecefX, int32_t ecefY, int32_t ecefZ, uint32_t posAcc, sfe_ublox_mga_assist_ack_e mgaAck, uint16_t maxWait); + * The units for ```ecefX/Y/Z``` and ```posAcc``` (stddev) are cm + * bool setPositionAssistanceLLH(int32_t lat, int32_t lon, int32_t alt, uint32_t posAcc, sfe_ublox_mga_assist_ack_e mgaAck, uint16_t maxWait); + * The units for ```lat``` and ```lon``` are degrees * 1e-7 (WGS84). The units for ```alt``` (WGS84) and ```posAcc``` (stddev) are cm (not m) + ## Additional Code Support for AssistNow Offline AssistNow Offline data downloaded from the u-blox server can contain 1-5 weeks of data. However, only the data for _today_ should be pushed the module. Sending data for past or future days will confuse the module. diff --git a/keywords.txt b/keywords.txt index 34f4716..e4d1b03 100644 --- a/keywords.txt +++ b/keywords.txt @@ -92,6 +92,8 @@ pushRawData KEYWORD2 pushAssistNowData KEYWORD2 setUTCTimeAssistance KEYWORD2 +setPositionAssistanceXYZ KEYWORD2 +setPositionAssistanceLLH KEYWORD2 findMGAANOForDate KEYWORD2 setFileBufferSize KEYWORD2 diff --git a/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp b/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp index e1643c5..984fbb7 100644 --- a/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp +++ b/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp @@ -4281,6 +4281,116 @@ bool SFE_UBLOX_GNSS::setUTCTimeAssistance(uint16_t year, uint8_t month, uint8_t return (pushAssistNowDataInternal(0, false, iniTimeUTC, 32, mgaAck, maxWait) == 1); } +// Provide initial position assistance +// The units for ecefX/Y/Z and posAcc (stddev) are cm. +bool SFE_UBLOX_GNSS::setPositionAssistanceXYZ(int32_t ecefX, int32_t ecefY, int32_t ecefZ, uint32_t posAcc, sfe_ublox_mga_assist_ack_e mgaAck, uint16_t maxWait) +{ + uint8_t iniPosXYZ[28]; // Create the UBX-MGA-INI-POS_XYZ message by hand + memset(iniPosXYZ, 0x00, 28); // Set all unused / reserved bytes and the checksum to zero + + iniPosXYZ[0] = UBX_SYNCH_1; // Sync char 1 + iniPosXYZ[1] = UBX_SYNCH_2; // Sync char 2 + iniPosXYZ[2] = UBX_CLASS_MGA; // Class + iniPosXYZ[3] = UBX_MGA_INI_POS_XYZ; // ID + iniPosXYZ[4] = 20; // Length LSB + iniPosXYZ[5] = 0x00; // Length MSB + iniPosXYZ[6] = 0x00; // type + iniPosXYZ[7] = 0x00; // version + + union // Use a union to convert from int32_t to uint32_t + { + int32_t signedLong; + uint32_t unsignedLong; + } signedUnsigned; + + signedUnsigned.signedLong = ecefX; + iniPosXYZ[10] = (uint8_t)(signedUnsigned.unsignedLong & 0xFF); // LSB + iniPosXYZ[11] = (uint8_t)((signedUnsigned.unsignedLong >> 8) & 0xFF); + iniPosXYZ[12] = (uint8_t)((signedUnsigned.unsignedLong >> 16) & 0xFF); + iniPosXYZ[13] = (uint8_t)(signedUnsigned.unsignedLong >> 24); // MSB + + signedUnsigned.signedLong = ecefY; + iniPosXYZ[14] = (uint8_t)(signedUnsigned.unsignedLong & 0xFF); // LSB + iniPosXYZ[15] = (uint8_t)((signedUnsigned.unsignedLong >> 8) & 0xFF); + iniPosXYZ[16] = (uint8_t)((signedUnsigned.unsignedLong >> 16) & 0xFF); + iniPosXYZ[17] = (uint8_t)(signedUnsigned.unsignedLong >> 24); // MSB + + signedUnsigned.signedLong = ecefZ; + iniPosXYZ[18] = (uint8_t)(signedUnsigned.unsignedLong & 0xFF); // LSB + iniPosXYZ[19] = (uint8_t)((signedUnsigned.unsignedLong >> 8) & 0xFF); + iniPosXYZ[20] = (uint8_t)((signedUnsigned.unsignedLong >> 16) & 0xFF); + iniPosXYZ[21] = (uint8_t)(signedUnsigned.unsignedLong >> 24); // MSB + + iniPosXYZ[22] = (uint8_t)(posAcc & 0xFF); // LSB + iniPosXYZ[23] = (uint8_t)((posAcc >> 8) & 0xFF); + iniPosXYZ[24] = (uint8_t)((posAcc >> 16) & 0xFF); + iniPosXYZ[25] = (uint8_t)(posAcc >> 24); // MSB + + for (uint8_t i = 2; i < 26; i++) // Calculate the checksum + { + iniPosXYZ[26] += iniPosXYZ[i]; + iniPosXYZ[27] += iniPosXYZ[26]; + } + + // Return true if the one packet was pushed successfully + return (pushAssistNowDataInternal(0, false, iniPosXYZ, 28, mgaAck, maxWait) == 1); +} + +// The units for lat and lon are degrees * 1e-7 (WGS84) +// The units for alt (WGS84) and posAcc (stddev) are cm. +bool SFE_UBLOX_GNSS::setPositionAssistanceLLH(int32_t lat, int32_t lon, int32_t alt, uint32_t posAcc, sfe_ublox_mga_assist_ack_e mgaAck, uint16_t maxWait) +{ + uint8_t iniPosLLH[28]; // Create the UBX-MGA-INI-POS_LLH message by hand + memset(iniPosLLH, 0x00, 28); // Set all unused / reserved bytes and the checksum to zero + + iniPosLLH[0] = UBX_SYNCH_1; // Sync char 1 + iniPosLLH[1] = UBX_SYNCH_2; // Sync char 2 + iniPosLLH[2] = UBX_CLASS_MGA; // Class + iniPosLLH[3] = UBX_MGA_INI_POS_LLH; // ID + iniPosLLH[4] = 20; // Length LSB + iniPosLLH[5] = 0x00; // Length MSB + iniPosLLH[6] = 0x01; // type + iniPosLLH[7] = 0x00; // version + + union // Use a union to convert from int32_t to uint32_t + { + int32_t signedLong; + uint32_t unsignedLong; + } signedUnsigned; + + signedUnsigned.signedLong = lat; + iniPosLLH[10] = (uint8_t)(signedUnsigned.unsignedLong & 0xFF); // LSB + iniPosLLH[11] = (uint8_t)((signedUnsigned.unsignedLong >> 8) & 0xFF); + iniPosLLH[12] = (uint8_t)((signedUnsigned.unsignedLong >> 16) & 0xFF); + iniPosLLH[13] = (uint8_t)(signedUnsigned.unsignedLong >> 24); // MSB + + signedUnsigned.signedLong = lon; + iniPosLLH[14] = (uint8_t)(signedUnsigned.unsignedLong & 0xFF); // LSB + iniPosLLH[15] = (uint8_t)((signedUnsigned.unsignedLong >> 8) & 0xFF); + iniPosLLH[16] = (uint8_t)((signedUnsigned.unsignedLong >> 16) & 0xFF); + iniPosLLH[17] = (uint8_t)(signedUnsigned.unsignedLong >> 24); // MSB + + signedUnsigned.signedLong = alt; + iniPosLLH[18] = (uint8_t)(signedUnsigned.unsignedLong & 0xFF); // LSB + iniPosLLH[19] = (uint8_t)((signedUnsigned.unsignedLong >> 8) & 0xFF); + iniPosLLH[20] = (uint8_t)((signedUnsigned.unsignedLong >> 16) & 0xFF); + iniPosLLH[21] = (uint8_t)(signedUnsigned.unsignedLong >> 24); // MSB + + iniPosLLH[22] = (uint8_t)(posAcc & 0xFF); // LSB + iniPosLLH[23] = (uint8_t)((posAcc >> 8) & 0xFF); + iniPosLLH[24] = (uint8_t)((posAcc >> 16) & 0xFF); + iniPosLLH[25] = (uint8_t)(posAcc >> 24); // MSB + + for (uint8_t i = 2; i < 26; i++) // Calculate the checksum + { + iniPosLLH[26] += iniPosLLH[i]; + iniPosLLH[27] += iniPosLLH[26]; + } + + // Return true if the one packet was pushed successfully + return (pushAssistNowDataInternal(0, false, iniPosLLH, 28, mgaAck, maxWait) == 1); +} + // Find the start of the AssistNow Offline (UBX_MGA_ANO) data for the chosen day // The daysIntoFture parameter makes it easy to get the data for (e.g.) tomorrow based on today's date // Returns numDataBytes if unsuccessful diff --git a/src/SparkFun_u-blox_GNSS_Arduino_Library.h b/src/SparkFun_u-blox_GNSS_Arduino_Library.h index 06eaf7a..806cc64 100644 --- a/src/SparkFun_u-blox_GNSS_Arduino_Library.h +++ b/src/SparkFun_u-blox_GNSS_Arduino_Library.h @@ -726,6 +726,13 @@ public: #define defaultMGAINITIMEsource 0 // Set default source to none, i.e. on receipt of message (will be inaccurate!) bool setUTCTimeAssistance(uint16_t year, uint8_t month, uint8_t day, uint8_t hour, uint8_t minute, uint8_t second, uint32_t nanos = 0, uint16_t tAccS = defaultMGAINITIMEtAccS, uint32_t tAccNs = defaultMGAINITIMEtAccNs, uint8_t source = defaultMGAINITIMEsource, sfe_ublox_mga_assist_ack_e mgaAck = SFE_UBLOX_MGA_ASSIST_ACK_NO, uint16_t maxWait = defaultMGAdelay); + // Provide initial position assistance + // The units for ecefX/Y/Z and posAcc (stddev) are cm. + bool setPositionAssistanceXYZ(int32_t ecefX, int32_t ecefY, int32_t ecefZ, uint32_t posAcc, sfe_ublox_mga_assist_ack_e mgaAck = SFE_UBLOX_MGA_ASSIST_ACK_NO, uint16_t maxWait = defaultMGAdelay); + // The units for lat and lon are degrees * 1e-7 (WGS84) + // The units for alt (WGS84) and posAcc (stddev) are cm. + bool setPositionAssistanceLLH(int32_t lat, int32_t lon, int32_t alt, uint32_t posAcc, sfe_ublox_mga_assist_ack_e mgaAck = SFE_UBLOX_MGA_ASSIST_ACK_NO, uint16_t maxWait = defaultMGAdelay); + // Find the start of the AssistNow Offline (UBX_MGA_ANO) data for the chosen day // The daysIntoFture parameter makes it easy to get the data for (e.g.) tomorrow based on today's date // Returns numDataBytes if unsuccessful