mirror of
https://github.com/letscontrolit/ESPEasy.git
synced 2026-09-12 01:24:04 +00:00
275 lines
8.8 KiB
C
275 lines
8.8 KiB
C
#ifndef PLUGINSTRUCTS_P082_DATA_STRUCT_H
|
|
#define PLUGINSTRUCTS_P082_DATA_STRUCT_H
|
|
|
|
#include "../../_Plugin_Helper.h"
|
|
#ifdef USES_P082
|
|
|
|
# include <TinyGPS++.h>
|
|
# include <ESPeasySerial.h>
|
|
# include "../Helpers/ModuloOversamplingHelper.h"
|
|
|
|
# ifndef BUILD_NO_DEBUG
|
|
# define P082_SEND_GPS_TO_LOG
|
|
|
|
// # define P082_USE_U_BLOX_SPECIFIC // TD-er: Disabled for now, as it is not working reliable/predictable
|
|
# endif // ifndef BUILD_NO_DEBUG
|
|
|
|
# define P082_TIMESTAMP_AGE 1000
|
|
# define P082_DEFAULT_FIX_TIMEOUT 2500 // TTL of fix status in ms since last update
|
|
|
|
|
|
# define P082_TIMEOUT PCONFIG(0)
|
|
# define P082_TIMEOUT_LABEL PCONFIG_LABEL(0)
|
|
# define P082_BAUDRATE PCONFIG(1)
|
|
# define P082_BAUDRATE_LABEL PCONFIG_LABEL(1)
|
|
# define P082_DISTANCE PCONFIG(2)
|
|
# define P082_DISTANCE_LABEL PCONFIG_LABEL(2)
|
|
|
|
# define P082_QUERY1_CONFIG_POS 3
|
|
# define P082_QUERY1 PCONFIG(3) // P082_QUERY1_CONFIG_POS
|
|
# define P082_QUERY2 PCONFIG(4) // P082_QUERY1_CONFIG_POS + 1
|
|
# define P082_QUERY3 PCONFIG(5) // P082_QUERY1_CONFIG_POS + 2
|
|
# define P082_QUERY4 PCONFIG(6) // P082_QUERY1_CONFIG_POS + 3
|
|
|
|
# define P082_LONG_REF PCONFIG_FLOAT(0)
|
|
# define P082_LAT_REF PCONFIG_FLOAT(1)
|
|
# ifdef P082_USE_U_BLOX_SPECIFIC
|
|
# define P082_POWER_MODE PCONFIG(7)
|
|
# define P082_DYNAMIC_MODEL PCONFIG_LONG(0)
|
|
# endif // P082_USE_U_BLOX_SPECIFIC
|
|
|
|
# define P082_NR_OUTPUT_VALUES VARS_PER_TASK
|
|
|
|
|
|
# define P082_DISTANCE_DFLT 0 // Disable update per distance travelled.
|
|
# define P082_QUERY1_DFLT P082_query::P082_QUERY_LONG
|
|
# define P082_QUERY2_DFLT P082_query::P082_QUERY_LAT
|
|
# define P082_QUERY3_DFLT P082_query::P082_QUERY_ALT
|
|
# define P082_QUERY4_DFLT P082_query::P082_QUERY_SPD
|
|
|
|
|
|
enum class P082_query : uint8_t {
|
|
P082_QUERY_LONG = 0,
|
|
P082_QUERY_LAT = 1,
|
|
P082_QUERY_ALT = 2,
|
|
P082_QUERY_SPD = 3,
|
|
P082_QUERY_SATVIS = 4,
|
|
P082_QUERY_SATUSE = 5,
|
|
P082_QUERY_HDOP = 6,
|
|
P082_QUERY_FIXQ = 7,
|
|
P082_QUERY_DB_MAX = 8,
|
|
P082_QUERY_CHKSUM_FAIL = 9,
|
|
P082_QUERY_DISTANCE = 10,
|
|
P082_QUERY_DIST_REF = 11,
|
|
P082_QUERY_COURSE = 12,
|
|
P082_NR_OUTPUT_OPTIONS
|
|
};
|
|
|
|
const __FlashStringHelper* Plugin_082_valuename(P082_query value_nr,
|
|
bool displayString);
|
|
|
|
P082_query Plugin_082_from_valuename(const String& valuename);
|
|
|
|
|
|
enum class P082_PowerMode : uint8_t {
|
|
Max_Performance = 0,
|
|
Power_Save = 1,
|
|
Eco = 2
|
|
};
|
|
|
|
const __FlashStringHelper* toString(P082_PowerMode mode);
|
|
|
|
|
|
enum class P082_DynamicModel : uint8_t {
|
|
Portable = 0,
|
|
Stationary = 2,
|
|
Pedestrian = 3,
|
|
Automotive = 4,
|
|
Sea = 5,
|
|
Airborne_1g = 6, // airborne with <1g acceleration
|
|
Airborne_2g = 7, // airborne with <2g acceleration
|
|
Airborne_4g = 8, // airborne with <4g acceleration
|
|
Wrist = 9, // Only recommended for wrist-worn applications. Receiver will filter out armmotion (just available for protocol version
|
|
// > 17).
|
|
Bike = 10 // Used for applications with equivalent dynamics to those of a motor bike. Lowvertical acceleration assumed. (supported
|
|
// in protocol versions 19.2)
|
|
};
|
|
|
|
const __FlashStringHelper* toString(P082_DynamicModel model);
|
|
|
|
|
|
// Class to help determine the most likely fraction of a second
|
|
// when the burst of messages starts
|
|
// This fraction is relative to the system micros.
|
|
struct P082_software_pps {
|
|
P082_software_pps();
|
|
|
|
// Keep track of fraction of second relative to the system micros
|
|
// when the start of the sentence ('$') was received.
|
|
void addStartOfSentence(uint32_t bytesAvailableInSerialBuffer);
|
|
|
|
// Commit the last recorded start of sentence time to the
|
|
// matching ModuloOversamplingHelper
|
|
void setSentenceType(TinyGPSPlus::GPS_Sentence_type sentenceType, uint32_t bytesAvailableInSerialBuffer);
|
|
|
|
void setBaudrate(uint32_t baudrate);
|
|
|
|
// Search for the second fraction of the sentence
|
|
// starting the burst of sentences, marking the start of a second.
|
|
bool getPPS(uint32_t& second_frac_in_usec) const;
|
|
|
|
#ifndef BUILD_NO_DEBUG
|
|
String getStats() const;
|
|
#endif
|
|
|
|
private:
|
|
|
|
uint64_t bytesToUsec(uint32_t bytes) const;
|
|
|
|
ModuloOversamplingHelper<uint32_t, uint32_t>_second_frac_in_usec[TinyGPSPlus::GPS_SENTENCE_OTHER]{};
|
|
|
|
uint64_t _cur_start_sentence_usec = 0;
|
|
|
|
int32_t _baudrate = 0;
|
|
};
|
|
|
|
|
|
struct P082_data_struct : public PluginTaskData_base {
|
|
// Enum is being stored, so don't change int values
|
|
|
|
|
|
P082_data_struct();
|
|
|
|
virtual ~P082_data_struct();
|
|
|
|
// void reset();
|
|
|
|
bool init(ESPEasySerialPort port,
|
|
const int16_t serial_rx,
|
|
const int16_t serial_tx,
|
|
const int8_t pps_pin);
|
|
|
|
bool isInitialized() const {
|
|
return gps != nullptr && easySerial != nullptr;
|
|
}
|
|
|
|
bool loop();
|
|
|
|
bool hasFix(unsigned int maxAge_msec);
|
|
|
|
bool storeCurPos(unsigned int maxAge_msec);
|
|
|
|
// Return the distance in meters compared to last stored position.
|
|
// @retval -1 when no fix.
|
|
ESPEASY_RULES_FLOAT_TYPE distanceSinceLast(unsigned int maxAge_msec);
|
|
|
|
private:
|
|
|
|
// Return the GPS time stamp, which is in UTC.
|
|
// @param age is the time in msec since the last update of the time +
|
|
// additional centiseconds given by the GPS.
|
|
bool getDateTime(struct tm& dateTime,
|
|
uint8_t & centiseconds,
|
|
uint32_t & age,
|
|
bool & updated);
|
|
|
|
public:
|
|
|
|
bool getDateTime(struct tm& dateTime) const;
|
|
|
|
// Try to fetch 5 timestamps in a row, filter out the peaks and use the average to set the
|
|
bool tryUpdateSystemTime();
|
|
|
|
// Send command to GPS to put it in PMREQ backup mode (UBLOX only)
|
|
// @retval true when successful in sending command
|
|
bool powerDown();
|
|
|
|
// Send some characters to GPS to wake up
|
|
bool wakeUp();
|
|
# ifdef P082_USE_U_BLOX_SPECIFIC
|
|
bool setPowerMode(P082_PowerMode mode);
|
|
|
|
bool setDynamicModel(P082_DynamicModel model);
|
|
# endif // ifdef P082_USE_U_BLOX_SPECIFIC
|
|
|
|
# if FEATURE_PLUGIN_STATS
|
|
bool webformLoad_show_stats(struct EventStruct *event,
|
|
uint8_t var_index,
|
|
P082_query query_type) const;
|
|
|
|
# if FEATURE_CHART_JS
|
|
void webformLoad_show_position_scatterplot(struct EventStruct *event);
|
|
# endif // if FEATURE_CHART_JS
|
|
# endif // if FEATURE_PLUGIN_STATS
|
|
|
|
#ifndef BUILD_NO_DEBUG
|
|
String getPPSStats() const;
|
|
#endif
|
|
|
|
|
|
private:
|
|
|
|
# ifdef P082_USE_U_BLOX_SPECIFIC
|
|
|
|
// Compute checksum
|
|
// Caller should offset the data pointer to the correct start where the CRC should start.
|
|
// @param size The length over which the CRC should be computed
|
|
// @param CK_A, CK_B The 2 checksum bytes.
|
|
static void computeUbloxChecksum(const uint8_t *data,
|
|
size_t size,
|
|
uint8_t & CK_A,
|
|
uint8_t & CK_B);
|
|
|
|
// Set checksum.
|
|
// First 2 bytes of the array are skipped
|
|
static void setUbloxChecksum(uint8_t *data,
|
|
size_t size);
|
|
# endif // ifdef P082_USE_U_BLOX_SPECIFIC
|
|
|
|
bool writeToGPS(const uint8_t *data,
|
|
size_t size);
|
|
|
|
static void pps_interrupt(P082_data_struct *self);
|
|
|
|
public:
|
|
|
|
TinyGPSPlus *gps = nullptr;
|
|
ESPeasySerial *easySerial = nullptr;
|
|
|
|
ESPEASY_RULES_FLOAT_TYPE _last_lat{};
|
|
ESPEASY_RULES_FLOAT_TYPE _last_lng{};
|
|
ESPEASY_RULES_FLOAT_TYPE _ref_lat{};
|
|
ESPEASY_RULES_FLOAT_TYPE _ref_lng{};
|
|
ESPEASY_RULES_FLOAT_TYPE _distance{};
|
|
|
|
|
|
unsigned long _last_measurement = 0;
|
|
uint32_t _last_time = 0;
|
|
uint32_t _last_date = 0;
|
|
|
|
// uint32_t _start_sentence = 0;
|
|
// uint32_t _start_prev_sentence = 0;
|
|
// uint32_t _start_sequence = 0;
|
|
# ifdef P082_SEND_GPS_TO_LOG
|
|
String _lastSentence;
|
|
String _currentSentence;
|
|
# endif // ifdef P082_SEND_GPS_TO_LOG
|
|
|
|
float _cache[static_cast<uint8_t>(P082_query::P082_NR_OUTPUT_OPTIONS)]{};
|
|
|
|
OversamplingHelper<uint64_t, uint64_t>_oversampling_gps_time_offset_usec;
|
|
|
|
P082_software_pps _softwarePPS;
|
|
|
|
// When using PPS pin, we're only interested in the moment during a second when it triggers.
|
|
// So we keep only track of the micros() % 1000000 so we have some offset from the system micros counter.
|
|
// This will also be used to keep track of when the first sentence is received as the GPS will send those out in a burst at the start of a
|
|
// new second.
|
|
ESPEASY_VOLATILE(int64_t) _pps_time_micros = -1;
|
|
|
|
int8_t _ppsPin = -1;
|
|
};
|
|
|
|
#endif // ifdef USES_P082
|
|
#endif // ifndef PLUGINSTRUCTS_P082_DATA_STRUCT_H
|