2020-02-06 07:39:21 -08:00
|
|
|
#pragma once
|
|
|
|
|
|
2020-07-10 11:43:14 -07:00
|
|
|
#include "GPSStatus.h"
|
|
|
|
|
#include "Observer.h"
|
2020-10-10 09:57:57 +08:00
|
|
|
#include "concurrency/OSThread.h"
|
2020-05-04 11:15:05 -07:00
|
|
|
|
2023-01-21 06:32:41 -05:00
|
|
|
struct uBloxGnssModelInfo {
|
|
|
|
|
char swVersion[30];
|
|
|
|
|
char hwVersion[10];
|
2022-09-16 02:43:04 +08:00
|
|
|
uint8_t extensionNo;
|
2023-01-21 06:32:41 -05:00
|
|
|
char extension[10][30];
|
|
|
|
|
};
|
2022-09-16 02:43:04 +08:00
|
|
|
|
2023-01-21 06:32:41 -05:00
|
|
|
typedef enum {
|
|
|
|
|
GNSS_MODEL_MTK,
|
|
|
|
|
GNSS_MODEL_UBLOX,
|
2023-07-16 23:57:14 +02:00
|
|
|
GNSS_MODEL_UC6850,
|
2023-07-08 16:30:52 -07:00
|
|
|
GNSS_MODEL_UNKNOWN,
|
2023-01-21 06:32:41 -05:00
|
|
|
} GnssModel_t;
|
2022-09-16 02:43:04 +08:00
|
|
|
|
2020-06-20 18:59:41 -07:00
|
|
|
// Generate a string representation of DOP
|
|
|
|
|
const char *getDOPString(uint32_t dop);
|
|
|
|
|
|
2020-02-06 07:39:21 -08:00
|
|
|
/**
|
|
|
|
|
* A gps class that only reads from the GPS periodically (and FIXME - eventually keeps the gps powered down except when reading)
|
2020-03-18 19:15:51 -07:00
|
|
|
*
|
2020-02-06 07:39:21 -08:00
|
|
|
* When new data is available it will notify observers.
|
|
|
|
|
*/
|
2020-10-10 09:57:57 +08:00
|
|
|
class GPS : private concurrency::OSThread
|
2020-02-06 07:39:21 -08:00
|
|
|
{
|
2020-10-01 09:11:54 -07:00
|
|
|
private:
|
2020-10-06 06:07:30 +08:00
|
|
|
uint32_t lastWakeStartMsec = 0, lastSleepStartMsec = 0, lastWhileActiveMsec = 0;
|
2020-10-01 09:11:54 -07:00
|
|
|
|
2021-10-24 12:38:35 +00:00
|
|
|
/**
|
|
|
|
|
* hasValidLocation - indicates that the position variables contain a complete
|
|
|
|
|
* GPS location, valid and fresh (< gps_update_interval + gps_attempt_time)
|
|
|
|
|
*/
|
2020-05-04 11:15:05 -07:00
|
|
|
bool hasValidLocation = false; // default to false, until we complete our first read
|
2020-02-19 08:17:28 -08:00
|
|
|
|
2020-10-01 09:11:54 -07:00
|
|
|
bool isAwake = false; // true if we want a location right now
|
|
|
|
|
|
|
|
|
|
bool wakeAllowed = true; // false if gps must be forced to sleep regardless of what time it is
|
2020-09-28 17:04:19 -07:00
|
|
|
|
2020-10-10 09:20:38 +08:00
|
|
|
bool shouldPublish = false; // If we've changed GPS state, this will force a publish the next loop()
|
|
|
|
|
|
|
|
|
|
bool hasGPS = false; // Do we have a GPS we are talking to
|
|
|
|
|
|
|
|
|
|
uint8_t numSatellites = 0;
|
|
|
|
|
|
2020-10-01 09:11:54 -07:00
|
|
|
CallbackObserver<GPS, void *> notifySleepObserver = CallbackObserver<GPS, void *>(this, &GPS::prepareSleep);
|
2020-10-30 17:05:32 +08:00
|
|
|
CallbackObserver<GPS, void *> notifyDeepSleepObserver = CallbackObserver<GPS, void *>(this, &GPS::prepareDeepSleep);
|
2022-12-17 23:32:20 +01:00
|
|
|
CallbackObserver<GPS, void *> notifyGPSSleepObserver = CallbackObserver<GPS, void *>(this, &GPS::prepareDeepSleep);
|
2020-10-01 09:11:54 -07:00
|
|
|
|
2020-07-10 11:43:14 -07:00
|
|
|
public:
|
|
|
|
|
/** If !NULL we will use this serial port to construct our GPS */
|
2020-07-09 21:27:34 -07:00
|
|
|
static HardwareSerial *_serial_gps;
|
2020-02-19 10:53:09 -08:00
|
|
|
|
2023-01-21 18:22:19 +01:00
|
|
|
meshtastic_Position p = meshtastic_Position_init_default;
|
2021-09-05 15:10:06 +00:00
|
|
|
|
2020-10-10 09:57:57 +08:00
|
|
|
GPS() : concurrency::OSThread("GPS") {}
|
|
|
|
|
|
2021-03-10 15:21:54 +08:00
|
|
|
virtual ~GPS();
|
2020-02-21 12:24:35 -08:00
|
|
|
|
2020-08-12 15:51:57 -07:00
|
|
|
/** We will notify this observable anytime GPS state has changed meaningfully */
|
2020-06-28 18:17:52 -07:00
|
|
|
Observable<const meshtastic::GPSStatus *> newStatus;
|
2020-06-27 21:19:49 -07:00
|
|
|
|
2020-05-04 11:15:05 -07:00
|
|
|
/**
|
|
|
|
|
* Returns true if we succeeded
|
|
|
|
|
*/
|
2020-10-01 09:11:54 -07:00
|
|
|
virtual bool setup();
|
2020-05-04 17:39:57 -07:00
|
|
|
|
2021-09-02 13:11:11 +00:00
|
|
|
/// Returns true if we have acquired GPS lock.
|
|
|
|
|
virtual bool hasLock();
|
2020-03-26 09:24:53 -07:00
|
|
|
|
2022-05-21 22:38:33 +02:00
|
|
|
/// Returns true if there's valid data flow with the chip.
|
|
|
|
|
virtual bool hasFlow();
|
|
|
|
|
|
2020-10-10 09:20:38 +08:00
|
|
|
/// Return true if we are connected to a GPS
|
|
|
|
|
bool isConnected() const { return hasGPS; }
|
|
|
|
|
|
2023-01-21 06:32:41 -05:00
|
|
|
bool isPowerSaving() const { return !config.position.gps_enabled; }
|
2022-12-17 23:32:20 +01:00
|
|
|
|
2020-09-28 17:04:19 -07:00
|
|
|
/**
|
2020-10-01 09:11:54 -07:00
|
|
|
* Restart our lock attempt - try to get and broadcast a GPS reading ASAP
|
|
|
|
|
* called after the CPU wakes from light-sleep state
|
|
|
|
|
*
|
|
|
|
|
* Or set to false, to disallow any sort of waking
|
|
|
|
|
* */
|
|
|
|
|
void forceWake(bool on);
|
|
|
|
|
|
2021-03-14 19:00:20 -07:00
|
|
|
// Some GPS modules (ublock) require factory reset
|
|
|
|
|
virtual bool factoryReset() { return true; }
|
|
|
|
|
|
2020-10-01 09:11:54 -07:00
|
|
|
protected:
|
2020-10-05 15:29:26 +08:00
|
|
|
/// Do gps chipset specific init, return true for success
|
2020-10-25 17:07:54 +08:00
|
|
|
virtual bool setupGPS();
|
2020-10-05 15:29:26 +08:00
|
|
|
|
2020-10-01 09:11:54 -07:00
|
|
|
/// If possible force the GPS into sleep/low power mode
|
2020-10-13 13:59:06 +08:00
|
|
|
virtual void sleep();
|
2020-10-01 09:11:54 -07:00
|
|
|
|
|
|
|
|
/// wake the GPS into normal operation mode
|
2020-10-13 13:59:06 +08:00
|
|
|
virtual void wake();
|
2020-10-01 09:11:54 -07:00
|
|
|
|
|
|
|
|
/** Subclasses should look for serial rx characters here and feed it to their GPS parser
|
|
|
|
|
*
|
|
|
|
|
* Return true if we received a valid message from the GPS
|
2020-09-28 17:04:19 -07:00
|
|
|
*/
|
2020-10-01 09:11:54 -07:00
|
|
|
virtual bool whileIdle() = 0;
|
2020-09-28 17:04:19 -07:00
|
|
|
|
2020-10-06 06:07:30 +08:00
|
|
|
/** Idle processing while GPS is looking for lock, called once per secondish */
|
2020-10-05 14:43:44 +08:00
|
|
|
virtual void whileActive() {}
|
|
|
|
|
|
2020-05-04 11:15:05 -07:00
|
|
|
/**
|
2020-10-01 09:11:54 -07:00
|
|
|
* Perform any processing that should be done only while the GPS is awake and looking for a fix.
|
|
|
|
|
* Override this method to check for new locations
|
|
|
|
|
*
|
|
|
|
|
* @return true if we've acquired a time
|
|
|
|
|
*/
|
|
|
|
|
virtual bool lookForTime() = 0;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Perform any processing that should be done only while the GPS is awake and looking for a fix.
|
|
|
|
|
* Override this method to check for new locations
|
|
|
|
|
*
|
|
|
|
|
* @return true if we've acquired a new location
|
|
|
|
|
*/
|
|
|
|
|
virtual bool lookForLocation() = 0;
|
2020-09-28 17:04:19 -07:00
|
|
|
|
2020-10-10 09:20:38 +08:00
|
|
|
/// Record that we have a GPS
|
|
|
|
|
void setConnected();
|
|
|
|
|
|
|
|
|
|
void setNumSatellites(uint8_t n);
|
|
|
|
|
|
2020-10-01 09:11:54 -07:00
|
|
|
private:
|
|
|
|
|
/// Prepare the GPS for the cpu entering deep or light sleep, expect to be gone for at least 100s of msecs
|
|
|
|
|
/// always returns 0 to indicate okay to sleep
|
|
|
|
|
int prepareSleep(void *unused);
|
2020-09-28 17:04:19 -07:00
|
|
|
|
2020-10-30 17:05:32 +08:00
|
|
|
/// Prepare the GPS for the cpu entering deep sleep, expect to be gone for at least 100s of msecs
|
|
|
|
|
/// always returns 0 to indicate okay to sleep
|
|
|
|
|
int prepareDeepSleep(void *unused);
|
|
|
|
|
|
2023-07-02 02:20:40 +02:00
|
|
|
// Calculate checksum
|
|
|
|
|
void UBXChecksum(byte *message, size_t length);
|
|
|
|
|
|
2020-10-01 09:11:54 -07:00
|
|
|
/**
|
|
|
|
|
* Switch the GPS into a mode where we are actively looking for a lock, or alternatively switch GPS into a low power mode
|
|
|
|
|
*
|
|
|
|
|
* calls sleep/wake
|
|
|
|
|
*/
|
|
|
|
|
void setAwake(bool on);
|
2020-10-05 14:43:44 +08:00
|
|
|
|
2023-07-16 23:57:14 +02:00
|
|
|
/** Get how long we should stay looking for each aquisition
|
2020-10-05 14:43:44 +08:00
|
|
|
*/
|
|
|
|
|
uint32_t getWakeTime() const;
|
|
|
|
|
|
|
|
|
|
/** Get how long we should sleep between aqusition attempts
|
|
|
|
|
*/
|
|
|
|
|
uint32_t getSleepTime() const;
|
|
|
|
|
|
2022-05-17 19:48:48 +02:00
|
|
|
bool getACK(uint8_t c, uint8_t i);
|
|
|
|
|
|
2020-10-05 14:43:44 +08:00
|
|
|
/**
|
|
|
|
|
* Tell users we have new GPS readings
|
|
|
|
|
*/
|
|
|
|
|
void publishUpdate();
|
2020-10-10 09:57:57 +08:00
|
|
|
|
2022-01-24 17:24:40 +00:00
|
|
|
virtual int32_t runOnce() override;
|
2022-09-16 02:43:04 +08:00
|
|
|
|
2023-01-21 06:32:41 -05:00
|
|
|
// Get GNSS model
|
2023-07-16 23:57:14 +02:00
|
|
|
String getNMEA();
|
2022-09-16 02:43:04 +08:00
|
|
|
GnssModel_t probe();
|
|
|
|
|
|
|
|
|
|
int getAck(uint8_t *buffer, uint16_t size, uint8_t requestedClass, uint8_t requestedID);
|
|
|
|
|
|
2023-01-21 06:32:41 -05:00
|
|
|
// delay counter to allow more sats before fixed position stops GPS thread
|
|
|
|
|
uint8_t fixeddelayCtr = 0;
|
|
|
|
|
|
2022-09-16 02:43:04 +08:00
|
|
|
protected:
|
2023-07-08 16:30:52 -07:00
|
|
|
GnssModel_t gnssModel = GNSS_MODEL_UNKNOWN;
|
2020-02-06 07:39:21 -08:00
|
|
|
};
|
|
|
|
|
|
2023-01-21 06:32:41 -05:00
|
|
|
// Creates an instance of the GPS class.
|
2021-03-14 19:00:20 -07:00
|
|
|
// Returns the new instance or null if the GPS is not present.
|
2023-01-21 06:32:41 -05:00
|
|
|
GPS *createGps();
|
2021-03-14 19:00:20 -07:00
|
|
|
|
2023-07-02 02:20:40 +02:00
|
|
|
extern GPS *gps;
|