From 3cc57881beccc43287620fb5c9fcfae098d86381 Mon Sep 17 00:00:00 2001 From: Sara Damiano Date: Wed, 12 Feb 2020 19:52:22 -0500 Subject: [PATCH] Redo GSM location and GPS stringlessly Signed-off-by: Sara Damiano --- src/TinyGsmClientSIM5360.h | 10 ++++ src/TinyGsmClientSIM7000.h | 92 ++++++++++++++---------------------- src/TinyGsmClientSIM7600.h | 93 ++++++++++++++++++++++++------------ src/TinyGsmClientSIM800.h | 29 ++---------- src/TinyGsmClientSIM808.h | 85 ++++++++++++++------------------- src/TinyGsmClientSaraR4.h | 87 ++++++++++++++++++++++++++++++++-- src/TinyGsmClientUBLOX.h | 74 ++++++++++++++++++++++++++++- src/TinyGsmGPS.tpp | 22 +++++---- src/TinyGsmGSMLocation.tpp | 96 ++++++++++++++++++++++++++++++++++++-- 9 files changed, 409 insertions(+), 179 deletions(-) diff --git a/src/TinyGsmClientSIM5360.h b/src/TinyGsmClientSIM5360.h index b2a2651..c28a83e 100644 --- a/src/TinyGsmClientSIM5360.h +++ b/src/TinyGsmClientSIM5360.h @@ -16,6 +16,7 @@ #include "TinyGsmBattery.tpp" #include "TinyGsmGPRS.tpp" +#include "TinyGsmGSMLocation.tpp" #include "TinyGsmModem.tpp" #include "TinyGsmSMS.tpp" #include "TinyGsmTCP.tpp" @@ -43,6 +44,7 @@ class TinyGsmSim5360 : public TinyGsmModem, TINY_GSM_MUX_COUNT>, public TinyGsmSMS, public TinyGsmTime, + public TinyGsmGSMLocation, public TinyGsmBattery, public TinyGsmTemperature { friend class TinyGsmModem; @@ -51,6 +53,7 @@ class TinyGsmSim5360 : public TinyGsmModem, TINY_GSM_MUX_COUNT>; friend class TinyGsmSMS; friend class TinyGsmTime; + friend class TinyGsmGSMLocation; friend class TinyGsmBattery; friend class TinyGsmTemperature; @@ -401,6 +404,13 @@ class TinyGsmSim5360 : public TinyGsmModem, protected: // Follows all messaging functions per template + /* + * Location functions + */ + protected: + // SIM5360 and SIM7100 can return a GSM-based location from CLBS as per the + // template; SIM5320 doesn't not appear to be able to + /* * Time functions */ diff --git a/src/TinyGsmClientSIM7000.h b/src/TinyGsmClientSIM7000.h index 78cc9ad..5eab2a3 100644 --- a/src/TinyGsmClientSIM7000.h +++ b/src/TinyGsmClientSIM7000.h @@ -17,7 +17,6 @@ #include "TinyGsmBattery.tpp" #include "TinyGsmGPRS.tpp" #include "TinyGsmGPS.tpp" -#include "TinyGsmGSMLocation.tpp" #include "TinyGsmModem.tpp" #include "TinyGsmSMS.tpp" #include "TinyGsmTCP.tpp" @@ -43,7 +42,6 @@ class TinyGsmSim7000 : public TinyGsmModem, public TinyGsmTCP, public TinyGsmSMS, - public TinyGsmGSMLocation, public TinyGsmGPS, public TinyGsmTime, public TinyGsmBattery { @@ -52,7 +50,6 @@ class TinyGsmSim7000 : public TinyGsmModem, friend class TinyGsmTCP; friend class TinyGsmSMS; - friend class TinyGsmGSMLocation; friend class TinyGsmGPS; friend class TinyGsmTime; friend class TinyGsmBattery; @@ -390,13 +387,6 @@ class TinyGsmSim7000 : public TinyGsmModem, protected: // Follows all messaging functions per template - /* - * Location functions - */ - protected: - // Can return a location from CIPGSMLOC as per the template - - /* * GPS location functions */ @@ -426,16 +416,45 @@ class TinyGsmSim7000 : public TinyGsmModem, // get GPS informations bool getGPSImpl(float* lat, float* lon, float* speed = 0, int* alt = 0, - int* vsat = 0, int* usat = 0) { - // String buffer = ""; + int* vsat = 0, int* usat = 0, int* year = 0, int* month = 0, + int* day = 0, int* hour = 0, int* minute = 0, + int* second = 0) { bool fix = false; sendAT(GF("+CGNSINF")); if (waitResponse(GF(GSM_NL "+CGNSINF:")) != 1) { return false; } - streamSkipUntil(','); // GNSS run status - if (streamGetInt(',') == 1) fix = true; // fix status - streamSkipUntil(','); // UTC date & Time + streamSkipUntil(','); // GNSS run status + if (streamGetInt(',') == 1) fix = true; // fix status + + // UTC date & Time + char dtSBuff[7] = {'\0'}; + stream.readBytes(dtSBuff, 4); // Four digit year + dtSBuff[4] = '\0'; // null terminate buffer + if (year != NULL) *year = atoi(dtSBuff); // Convert to int + + stream.readBytes(dtSBuff, 2); // Two digit month + dtSBuff[2] = '\0'; + if (month != NULL) *month = atoi(dtSBuff); + + stream.readBytes(dtSBuff, 2); // Two digit day + dtSBuff[2] = '\0'; + if (day != NULL) *day = atoi(dtSBuff); + + stream.readBytes(dtSBuff, 2); // Two digit hour + dtSBuff[2] = '\0'; + if (hour != NULL) *hour = atoi(dtSBuff); + + stream.readBytes(dtSBuff, 2); // Two digit minute + dtSBuff[2] = '\0'; + if (minute != NULL) *minute = atoi(dtSBuff); + + stream.readBytes(dtSBuff, 6); // 6 digit second with subseconds + dtSBuff[6] = '\0'; + if (second != NULL) *second = atoi(dtSBuff); + // *secondWithSS = atof(dtSBuff); + streamSkipUntil(','); // Throw away the final comma + *lat = streamGetFloat(','); // Latitude *lon = streamGetFloat(','); // Longitude if (alt != NULL) *alt = streamGetFloat(','); // MSL Altitude @@ -459,49 +478,6 @@ class TinyGsmSim7000 : public TinyGsmModem, return fix; } - // get GPS time - bool getGPSTimeImpl(int* year, int* month, int* day, int* hour, int* minute, - int* second) { - bool fix = false; - char chr_buffer[12]; - sendAT(GF("+CGNSINF")); - if (waitResponse(GF(GSM_NL "+CGNSINF:")) != 1) { return false; } - - for (int i = 0; i < 3; i++) { - String buffer = stream.readStringUntil(','); - buffer.toCharArray(chr_buffer, sizeof(chr_buffer)); - switch (i) { - case 0: - // mode - break; - case 1: - // fixstatus - if (buffer.toInt() == 1) { fix = buffer.toInt(); } - break; - case 2: - *year = buffer.substring(0, 4).toInt(); - *month = buffer.substring(4, 6).toInt(); - *day = buffer.substring(6, 8).toInt(); - *hour = buffer.substring(8, 10).toInt(); - *minute = buffer.substring(10, 12).toInt(); - *second = buffer.substring(12, 14).toInt(); - break; - - default: - // if nothing else matches, do the default - // default is optional - break; - } - } - streamSkipUntil('\n'); - waitResponse(); - - if (fix) { - return true; - } else { - return false; - } - } /* * Time functions diff --git a/src/TinyGsmClientSIM7600.h b/src/TinyGsmClientSIM7600.h index 1fda2d2..78bebbd 100644 --- a/src/TinyGsmClientSIM7600.h +++ b/src/TinyGsmClientSIM7600.h @@ -17,6 +17,7 @@ #include "TinyGsmBattery.tpp" #include "TinyGsmGPRS.tpp" #include "TinyGsmGPS.tpp" +#include "TinyGsmGSMLocation.tpp" #include "TinyGsmModem.tpp" #include "TinyGsmSMS.tpp" #include "TinyGsmTCP.tpp" @@ -43,6 +44,7 @@ class TinyGsmSim7600 : public TinyGsmModem, public TinyGsmTCP, public TinyGsmSMS, + public TinyGsmGSMLocation, public TinyGsmGPS, public TinyGsmTime, public TinyGsmBattery, @@ -53,6 +55,7 @@ class TinyGsmSim7600 : public TinyGsmModem, TINY_GSM_MUX_COUNT>; friend class TinyGsmSMS; friend class TinyGsmGPS; + friend class TinyGsmGSMLocation; friend class TinyGsmTime; friend class TinyGsmBattery; friend class TinyGsmTemperature; @@ -85,7 +88,7 @@ class TinyGsmSim7600 : public TinyGsmModem, } public: - int connect(const char* host, uint16_t port, int timeout_s) { + virtual int connect(const char* host, uint16_t port, int timeout_s) { stop(); TINY_GSM_YIELD(); rx.clear(); @@ -396,8 +399,7 @@ class TinyGsmSim7600 : public TinyGsmModem, * Location functions */ protected: - String getGsmLocationImpl() TINY_GSM_ATTR_NOT_IMPLEMENTED; - + // Can return a GSM-based location from CLBS as per the template /* * GPS location functions @@ -427,39 +429,72 @@ class TinyGsmSim7600 : public TinyGsmModem, } // get GPS informations - bool getGPSImpl(float* lat, float* lon, float* speed = 0, int* alt = 0) { + bool getGPSImpl(float* lat, float* lon, float* speed = 0, int* alt = 0, + int* vsat = 0, int* usat = 0, int* year = 0, int* month = 0, + int* day = 0, int* hour = 0, int* minute = 0, + int* second = 0) { // String buffer = ""; - bool fix = false; sendAT(GF("+CGNSSINFO")); if (waitResponse(GF(GSM_NL "+CGNSSINFO:")) != 1) { return false; } - // streamSkipUntil(','); // mode - if (streamGetInt(',') == 1) - fix = true; // TODO(?) Shouldn't this be 2=2D Fix or 3=3DFix? - streamSkipUntil(','); // GPS satellite valid numbers - streamSkipUntil(','); // GLONASS satellite valid numbers - streamSkipUntil(','); // BEIDOU satellite valid numbers - *lat = streamGetFloat(','); // Latitude - streamSkipUntil(','); // N/S Indicator, N=north or S=south - *lon = streamGetFloat(','); // Longitude - streamSkipUntil(','); // E/W Indicator, E=east or W=west - streamSkipUntil(','); // Date. Output format is ddmmyy - streamSkipUntil(','); // UTC Time. Output format is hhmmss.s - if (alt != NULL) - *alt = streamGetFloat(','); // MSL Altitude. Unit is meters - if (speed != NULL) - *speed = streamGetFloat(','); // Speed Over Ground. Unit is knots. - streamSkipUntil(','); // Course. Degrees. - streamSkipUntil(','); // After set, will report GPS every x seconds - streamSkipUntil(','); // Position Dilution Of Precision - streamSkipUntil(','); // Horizontal Dilution Of Precision - streamSkipUntil(','); // Vertical Dilution Of Precision - streamSkipUntil('\n'); // TODO(?) is one more field reported?? + uint8_t fixMode = streamGetInt(','); // mode 2=2D Fix or 3=3DFix + // TODO(?) Can 1 be returned + if (fixMode == 1 || fixMode == 2 || fixMode == 3) { + streamSkipUntil(','); // GPS satellite valid numbers + streamSkipUntil(','); // GLONASS satellite valid numbers + streamSkipUntil(','); // BEIDOU satellite valid numbers + *lat = streamGetFloat(','); // Latitude + streamSkipUntil(','); // N/S Indicator, N=north or S=south + *lon = streamGetFloat(','); // Longitude + streamSkipUntil(','); // E/W Indicator, E=east or W=west + + // Date. Output format is ddmmyy + char dtSBuff[5] = {'\0'}; + stream.readBytes(dtSBuff, 2); // Two digit day + dtSBuff[2] = '\0'; // null terminate buffer + if (day != NULL) *day = atoi(dtSBuff); // Convert to int + + stream.readBytes(dtSBuff, 2); // Two digit month + dtSBuff[2] = '\0'; + if (month != NULL) *month = atoi(dtSBuff); + + stream.readBytes(dtSBuff, 2); // Two digit year + dtSBuff[2] = '\0'; + if (year != NULL) *year = atoi(dtSBuff); + streamSkipUntil(','); // Throw away the final comma + + // UTC Time. Output format is hhmmss.s + stream.readBytes(dtSBuff, 2); // Two digit hour + dtSBuff[2] = '\0'; + if (hour != NULL) *hour = atoi(dtSBuff); + + stream.readBytes(dtSBuff, 2); // Two digit minute + dtSBuff[2] = '\0'; + if (minute != NULL) *minute = atoi(dtSBuff); + + stream.readBytes(dtSBuff, 6); // 6 digit second with subseconds + dtSBuff[6] = '\0'; + if (second != NULL) *second = atoi(dtSBuff); + // *secondWithSS = atof(dtSBuff); + streamSkipUntil(','); // Throw away the final comma + + if (alt != NULL) + *alt = streamGetFloat(','); // MSL Altitude. Unit is meters + if (speed != NULL) + *speed = streamGetFloat(','); // Speed Over Ground. Unit is knots. + streamSkipUntil(','); // Course. Degrees. + streamSkipUntil(','); // After set, will report GPS every x seconds + streamSkipUntil(','); // Position Dilution Of Precision + streamSkipUntil(','); // Horizontal Dilution Of Precision + streamSkipUntil(','); // Vertical Dilution Of Precision + streamSkipUntil('\n'); // TODO(?) is one more field reported?? - waitResponse(); + waitResponse(); - return fix; + return true; + } + return false; } /* diff --git a/src/TinyGsmClientSIM800.h b/src/TinyGsmClientSIM800.h index 0a72750..f0abd1e 100644 --- a/src/TinyGsmClientSIM800.h +++ b/src/TinyGsmClientSIM800.h @@ -170,8 +170,7 @@ class TinyGsmSim800 // Enable Local Time Stamp for getting network time sendAT(GF("+CLTS=1")); - if (waitResponse(10000L) != 1) { return false; - } + if (waitResponse(10000L) != 1) { return false; } // Enable battery checks sendAT(GF("+CBATCHK=1")); @@ -408,30 +407,10 @@ class TinyGsmSim800 * Location functions */ protected: - // Can return a location from CIPGSMLOC as per the template + // Depending on the exacty model and firmware revision, should return a + // GSM-based location from CLBS as per the template + // TODO(?): Check number of digits in year (2 or 4) - String getGsmLocation() { - sendAT(GF("+CIPGSMLOC=1,1")); - if (waitResponse(10000L, GF(GSM_NL "+CIPGSMLOC:")) != 1) { - return ""; - } - String res = stream.readStringUntil('\n'); - waitResponse(); - res.trim(); - return res; - } - - String getBaseStationGsmLocation() { - sendAT(GF("+CLBS=1,1")); - if (waitResponse(10000L, GF(GSM_NL "+CLBS:")) != 1) { - return ""; - } - String res = stream.readStringUntil('\n'); - waitResponse(); - res.trim(); - return res; - } - /* * GPS location functions */ diff --git a/src/TinyGsmClientSIM808.h b/src/TinyGsmClientSIM808.h index d2853f5..8017fc0 100644 --- a/src/TinyGsmClientSIM808.h +++ b/src/TinyGsmClientSIM808.h @@ -57,17 +57,45 @@ class TinyGsmSim808 : public TinyGsmSim800, public TinyGsmGPS { // get GPS informations // works only with ans SIM808 V2 bool getGPSImpl(float* lat, float* lon, float* speed = 0, int* alt = 0, - int* vsat = 0, int* usat = 0) { - // String buffer = ""; - // char chr_buffer[12]; + int* vsat = 0, int* usat = 0, int* year = 0, int* month = 0, + int* day = 0, int* hour = 0, int* minute = 0, + int* second = 0) { bool fix = false; sendAT(GF("+CGNSINF")); if (waitResponse(GF(GSM_NL "+CGNSINF:")) != 1) { return false; } - streamSkipUntil(','); // GNSS run status - if (streamGetInt(',') == 1) fix = true; // fix status - streamSkipUntil(','); // UTC date & Time + streamSkipUntil(','); // GNSS run status + if (streamGetInt(',') == 1) fix = true; // fix status + + // UTC date & Time + char dtSBuff[7] = {'\0'}; + stream.readBytes(dtSBuff, 4); // Four digit year + dtSBuff[4] = '\0'; // null terminate buffer + if (year != NULL) *year = atoi(dtSBuff); // Convert to int + + stream.readBytes(dtSBuff, 2); // Two digit month + dtSBuff[2] = '\0'; + if (month != NULL) *month = atoi(dtSBuff); + + stream.readBytes(dtSBuff, 2); // Two digit day + dtSBuff[2] = '\0'; + if (day != NULL) *day = atoi(dtSBuff); + + stream.readBytes(dtSBuff, 2); // Two digit hour + dtSBuff[2] = '\0'; + if (hour != NULL) *hour = atoi(dtSBuff); + + stream.readBytes(dtSBuff, 2); // Two digit minute + dtSBuff[2] = '\0'; + if (minute != NULL) *minute = atoi(dtSBuff); + + stream.readBytes(dtSBuff, 6); // 6 digit second with subseconds + dtSBuff[6] = '\0'; + if (second != NULL) *second = atoi(dtSBuff); + // *secondWithSS = atof(dtSBuff); + streamSkipUntil(','); // Throw away the final comma + *lat = streamGetFloat(','); // Latitude *lon = streamGetFloat(','); // Longitude if (alt != NULL) *alt = streamGetFloat(','); // MSL Altitude @@ -91,51 +119,6 @@ class TinyGsmSim808 : public TinyGsmSim800, public TinyGsmGPS { return fix; } - - // get GPS time - // works only with SIM808 V2 - bool getGPSTimeImpl(int* year, int* month, int* day, int* hour, int* minute, - int* second) { - bool fix = false; - char chr_buffer[12]; - sendAT(GF("+CGNSINF")); - if (waitResponse(GF(GSM_NL "+CGNSINF:")) != 1) { return false; } - - for (int i = 0; i < 3; i++) { - String buffer = stream.readStringUntil(','); - buffer.toCharArray(chr_buffer, sizeof(chr_buffer)); - switch (i) { - case 0: - // mode - break; - case 1: - // fixstatus - if (buffer.toInt() == 1) { fix = buffer.toInt(); } - break; - case 2: - *year = buffer.substring(0, 4).toInt(); - *month = buffer.substring(4, 6).toInt(); - *day = buffer.substring(6, 8).toInt(); - *hour = buffer.substring(8, 10).toInt(); - *minute = buffer.substring(10, 12).toInt(); - *second = buffer.substring(12, 14).toInt(); - break; - - default: - // if nothing else matches, do the default - // default is optional - break; - } - } - streamSkipUntil('\n'); - waitResponse(); - - if (fix) { - return true; - } else { - return false; - } - } }; #endif // SRC_TINYGSMCLIENTSIM808_H_ diff --git a/src/TinyGsmClientSaraR4.h b/src/TinyGsmClientSaraR4.h index a700ec5..65dab14 100644 --- a/src/TinyGsmClientSaraR4.h +++ b/src/TinyGsmClientSaraR4.h @@ -425,15 +425,96 @@ class TinyGsmSaraR4 * Location functions */ protected: - String getGsmLocationImpl() { - sendAT(GF("+ULOC=2,3,0,120,1")); - if (waitResponse(30000L, GF(GSM_NL "+UULOC:")) != 1) { return ""; } + String getGsmLocationRawImpl() { + // AT+ULOC=,,,, + // - 2: single shot position + // - 2: use cellular CellLocate® location information + // - 0: standard (single-hypothesis) response + // - Timeout period in seconds + // - Target accuracy in meters (1 - 999999) + sendAT(GF("+ULOC=2,2,0,120,1")); + // wait for first "OK" + if (waitResponse(10000L) != 1) { return ""; } + // wait for the final result - wait full timeout time + if (waitResponse(120000L, GF(GSM_NL "+UULOC:")) != 1) { return ""; } String res = stream.readStringUntil('\n'); waitResponse(); res.trim(); return res; } + bool getGsmLocationImpl(float* lat, float* lon, float* accuracy = 0, + int* year = 0, int* month = 0, int* day = 0, + int* hour = 0, int* minute = 0, int* second = 0) { + // AT+ULOC=,,,, + // - 2: single shot position + // - 2: use cellular CellLocate® location information + // - 0: standard (single-hypothesis) response + // - Timeout period in seconds + // - Target accuracy in meters (1 - 999999) + sendAT(GF("+ULOC=2,2,0,120,1")); + // wait for first "OK" + if (waitResponse(10000L) != 1) { return false; } + // wait for the final result - wait full timeout time + if (waitResponse(120000L, GF(GSM_NL "+UULOC:")) != 1) { return false; } + + // +UULOC: ,