From 84293ed7251c45b7438d644e9e34baa3983d327a Mon Sep 17 00:00:00 2001 From: Carsten Schmiemann Date: Tue, 3 May 2022 00:18:10 +0200 Subject: [PATCH] Original project changes: GPS: add normalized signal quality level, add web UI live status info --- .../components/ovms_cellular/src/gsmnmea.cpp | 22 +++++++ .../ovms_location/src/ovms_location.cpp | 57 ++++++++++++------- .../ovms_location/src/ovms_location.h | 6 +- .../ovms_server_v2/src/ovms_server_v2.cpp | 8 +-- .../components/ovms_webserver/src/web_cfg.cpp | 13 +++-- OVMS.V3/main/metrics_standard.cpp | 2 + OVMS.V3/main/metrics_standard.h | 4 ++ 7 files changed, 80 insertions(+), 32 deletions(-) diff --git a/OVMS.V3/components/ovms_cellular/src/gsmnmea.cpp b/OVMS.V3/components/ovms_cellular/src/gsmnmea.cpp index 4058171..4d23711 100644 --- a/OVMS.V3/components/ovms_cellular/src/gsmnmea.cpp +++ b/OVMS.V3/components/ovms_cellular/src/gsmnmea.cpp @@ -191,12 +191,28 @@ void GsmNMEA::IncomingLine(const std::string line) *StdMetrics.ms_v_pos_gpsmode = (std::string) mode; *StdMetrics.ms_v_pos_satcount = (int) satcnt; *StdMetrics.ms_v_pos_gpshdop = (float) hdop; + + // Derive signal quality from lock status, satellite count and HDOP: + // quality ~ satcnt / hdop + *StdMetrics.ms_v_pos_gpssq = (int) LIMIT_MAX(gpslock * LIMIT_MIN(satcnt-1,0) / LIMIT_MIN(hdop,0.1) * 10, 100); + // Quality raises by satellite count and drops by HDOP. HDOP 1.0 = perfect. + // The calculation is designed to get 50% as the threshold for a "good" signal. + // GPS needs at least 4 satellites in view to get a position, but that will need + // HDOP << 1 to be considered reliable. 6 satellites are on the edge to "good" + // (with HDOP=1). Samples: + // 4 satellites / HDOP 1.0 → SQ 30% + // 4 satellites / HDOP 0.6 → SQ 50% + // 6 satellites / HDOP 1.0 → SQ 50% + // 9 satellites / HDOP 1.0 → SQ 80% + // 10 satellites / HDOP 0.9 → SQ 100% + // 10 satellites / HDOP 1.8 → SQ 50% if (gpslock) { *StdMetrics.ms_v_pos_latitude = (float) lat; *StdMetrics.ms_v_pos_longitude = (float) lon; *StdMetrics.ms_v_pos_altitude = (float) alt; + *StdMetrics.ms_v_pos_gpstime = (int) time(NULL); } // upodate gpslock last, so listeners will see updated lat/lon values: @@ -281,6 +297,12 @@ void GsmNMEA::Shutdown(bool hard) { ESP_LOGI(TAG, "Shutdown (direct)"); + *StdMetrics.ms_v_pos_gpsmode = (std::string) ""; + *StdMetrics.ms_v_pos_gpsspeed = (float) 0; + *StdMetrics.ms_v_pos_satcount = (int) 0; + *StdMetrics.ms_v_pos_gpshdop = (float) 500; + *StdMetrics.ms_v_pos_gpssq = (int) 0; + if (StdMetrics.ms_v_pos_gpslock->AsBool()) { *StdMetrics.ms_v_pos_gpslock = (bool) false; diff --git a/OVMS.V3/components/ovms_location/src/ovms_location.cpp b/OVMS.V3/components/ovms_location/src/ovms_location.cpp index ba94e10..923d2d0 100644 --- a/OVMS.V3/components/ovms_location/src/ovms_location.cpp +++ b/OVMS.V3/components/ovms_location/src/ovms_location.cpp @@ -439,7 +439,10 @@ void location_status(int verbosity, OvmsWriter* writer, OvmsCommand* cmd, int ar writer->printf("(%sGPS lock", MyLocations.m_gpslock ? "" : "without "); n = StandardMetrics.ms_v_pos_satcount->AsInt(); if (n > 0) - writer->printf(", %d satellite%s", n, n == 1 ? "" : "s"); + { + writer->printf(", %d satellite%s, %s", n, n == 1 ? "" : "s", + MyLocations.m_gpsgood ? "reliable" : "unreliable"); + } writer->puts(")"); if ((MyLocations.m_park_latitude != 0) || (MyLocations.m_park_longitude != 0)) @@ -618,6 +621,8 @@ OvmsLocations::OvmsLocations() m_ready = false; m_gpslock = false; + m_gpssq = 0; + m_gpsgood = false; m_latitude = 0; m_longitude = 0; m_park_latitude = 0; @@ -671,8 +676,8 @@ OvmsLocations::OvmsLocations() using std::placeholders::_1; using std::placeholders::_2; MyMetrics.RegisterListener(TAG, MS_V_POS_GPSLOCK, std::bind(&OvmsLocations::UpdatedGpsLock, this, _1)); - MyMetrics.RegisterListener(TAG, MS_V_POS_LATITUDE, std::bind(&OvmsLocations::UpdatedLatitude, this, _1)); - MyMetrics.RegisterListener(TAG, MS_V_POS_LONGITUDE, std::bind(&OvmsLocations::UpdatedLongitude, this, _1)); + MyMetrics.RegisterListener(TAG, MS_V_POS_GPSSQ, std::bind(&OvmsLocations::UpdatedGpsSQ, this, _1)); + MyMetrics.RegisterListener(TAG, MS_V_POS_GPSTIME, std::bind(&OvmsLocations::UpdatedPosition, this, _1)); MyMetrics.RegisterListener(TAG, MS_V_ENV_ON, std::bind(&OvmsLocations::UpdatedVehicleOn, this, _1)); MyEvents.RegisterEvent(TAG,"config.mounted", std::bind(&OvmsLocations::UpdatedConfig, this, _1, _2)); MyEvents.RegisterEvent(TAG,"config.changed", std::bind(&OvmsLocations::UpdatedConfig, this, _1, _2)); @@ -696,12 +701,6 @@ void OvmsLocations::UpdatedGpsLock(OvmsMetric* metric) m_gpslock = m->AsBool(); if (m_gpslock) { - if (!m_ready) - { - UpdateParkPosition(); - m_ready = true; - } - UpdateLocations(); MyEvents.SignalEvent("gps.lock.acquired", NULL); } else @@ -710,22 +709,36 @@ void OvmsLocations::UpdatedGpsLock(OvmsMetric* metric) } } -void OvmsLocations::UpdatedLatitude(OvmsMetric* metric) +void OvmsLocations::UpdatedGpsSQ(OvmsMetric* metric) { - OvmsMetricFloat* m = (OvmsMetricFloat*)metric; - m_latitude = m->AsFloat(); - if (m_gpslock) + m_gpssq = StdMetrics.ms_v_pos_gpssq->AsInt(); + int level_good = MyConfig.GetParamValueInt("vehicle", "gps.sq.good", 60); + int level_bad = MyConfig.GetParamValueInt("vehicle", "gps.sq.bad", 40); + if (level_bad >= level_good) level_bad = level_good - 1; + + if (!m_gpsgood && m_gpssq >= level_good) { + m_gpsgood = true; + if (!m_ready) + { + UpdateParkPosition(); + m_ready = true; + } UpdateLocations(); - CheckTheft(); + MyEvents.SignalEvent("gps.sq.good", NULL); + } + else if (m_gpsgood && m_gpssq <= level_bad) + { + m_gpsgood = false; + MyEvents.SignalEvent("gps.sq.bad", NULL); } } -void OvmsLocations::UpdatedLongitude(OvmsMetric* metric) +void OvmsLocations::UpdatedPosition(OvmsMetric* metric) { - OvmsMetricFloat* m = (OvmsMetricFloat*)metric; - m_longitude = m->AsFloat(); - if (m_gpslock) + m_latitude = StdMetrics.ms_v_pos_latitude->AsFloat(); + m_longitude = StdMetrics.ms_v_pos_longitude->AsFloat(); + if (m_gpsgood) { UpdateLocations(); CheckTheft(); @@ -753,13 +766,13 @@ void OvmsLocations::UpdateParkPosition() { m_park_latitude = m_latitude; m_park_longitude = m_longitude; - m_park_invalid = (!m_gpslock || StdMetrics.ms_v_pos_latitude->IsStale() || StdMetrics.ms_v_pos_longitude->IsStale()); + m_park_invalid = (!m_gpsgood || StdMetrics.ms_v_pos_latitude->IsStale() || StdMetrics.ms_v_pos_longitude->IsStale()); m_last_alarm = 0; - ESP_LOGI(TAG, "UpdateParkPosition: vehicle is parking @%0.6f,%0.6f gpslock=%d satcount=%d hdop=%.1f invalid=%d", + ESP_LOGI(TAG, "UpdateParkPosition: vehicle is parking @%0.6f,%0.6f gpslock=%d satcount=%d hdop=%.1f sq=%d invalid=%d", m_park_latitude, m_park_longitude, m_gpslock, StdMetrics.ms_v_pos_satcount->AsInt(), StdMetrics.ms_v_pos_gpshdop->AsFloat(), - m_park_invalid); + m_gpssq, m_park_invalid); } } @@ -813,7 +826,7 @@ void OvmsLocations::ReloadMap() } } - if (m_gpslock) UpdateLocations(); + if (m_gpsgood) UpdateLocations(); } void OvmsLocations::UpdateLocations() diff --git a/OVMS.V3/components/ovms_location/src/ovms_location.h b/OVMS.V3/components/ovms_location/src/ovms_location.h index 9b7f8c1..249822a 100644 --- a/OVMS.V3/components/ovms_location/src/ovms_location.h +++ b/OVMS.V3/components/ovms_location/src/ovms_location.h @@ -96,6 +96,8 @@ class OvmsLocations public: bool m_ready; bool m_gpslock; + int m_gpssq; + bool m_gpsgood; float m_latitude; float m_longitude; float m_park_latitude; @@ -113,8 +115,8 @@ class OvmsLocations public: void UpdatedGpsLock(OvmsMetric* metric); - void UpdatedLatitude(OvmsMetric* metric); - void UpdatedLongitude(OvmsMetric* metric); + void UpdatedGpsSQ(OvmsMetric* metric); + void UpdatedPosition(OvmsMetric* metric); void UpdatedVehicleOn(OvmsMetric* metric); void UpdatedConfig(std::string event, void* data); }; diff --git a/OVMS.V3/components/ovms_server_v2/src/ovms_server_v2.cpp b/OVMS.V3/components/ovms_server_v2/src/ovms_server_v2.cpp index 49b8bd7..25e8cfc 100644 --- a/OVMS.V3/components/ovms_server_v2/src/ovms_server_v2.cpp +++ b/OVMS.V3/components/ovms_server_v2/src/ovms_server_v2.cpp @@ -1182,6 +1182,7 @@ void OvmsServerV2::TransmitMsgGPS(bool always) StandardMetrics.ms_v_pos_direction->IsModifiedAndClear(MyOvmsServerV2Modifier) | StandardMetrics.ms_v_pos_altitude->IsModifiedAndClear(MyOvmsServerV2Modifier) | StandardMetrics.ms_v_pos_gpslock->IsModifiedAndClear(MyOvmsServerV2Modifier) | + StandardMetrics.ms_v_pos_gpssq->IsModifiedAndClear(MyOvmsServerV2Modifier) | StandardMetrics.ms_v_pos_gpsmode->IsModifiedAndClear(MyOvmsServerV2Modifier) | StandardMetrics.ms_v_pos_gpshdop->IsModifiedAndClear(MyOvmsServerV2Modifier) | StandardMetrics.ms_v_pos_satcount->IsModifiedAndClear(MyOvmsServerV2Modifier) | @@ -1198,10 +1199,7 @@ void OvmsServerV2::TransmitMsgGPS(bool always) if ((!always)&&(!modified)) return; bool stale = - StandardMetrics.ms_v_pos_latitude->IsStale() || - StandardMetrics.ms_v_pos_longitude->IsStale() || - StandardMetrics.ms_v_pos_direction->IsStale() || - StandardMetrics.ms_v_pos_altitude->IsStale(); + StandardMetrics.ms_v_pos_gpstime->IsStale(); char drivemode[10]; sprintf(drivemode, "%x", StandardMetrics.ms_v_env_drivemode->AsInt()); @@ -1244,6 +1242,8 @@ void OvmsServerV2::TransmitMsgGPS(bool always) << StandardMetrics.ms_v_pos_gpshdop->AsString("0", Native, 1) << "," << StandardMetrics.ms_v_pos_gpsspeed->AsString("0", units_speed, 1) + << "," + << StandardMetrics.ms_v_pos_gpssq->AsInt() ; Transmit(buffer.str().c_str()); diff --git a/OVMS.V3/components/ovms_webserver/src/web_cfg.cpp b/OVMS.V3/components/ovms_webserver/src/web_cfg.cpp index 58cc7a5..ae7649b 100644 --- a/OVMS.V3/components/ovms_webserver/src/web_cfg.cpp +++ b/OVMS.V3/components/ovms_webserver/src/web_cfg.cpp @@ -101,6 +101,13 @@ void OvmsWebServer::HandleStatus(PageEntry_t& p, PageContext_t& c) "
?dBm
" "" "" + "" + "GPS" + "" + "
?Satellites
" + "
?%
" + "" + "" "" "Main battery" "" @@ -137,7 +144,7 @@ void OvmsWebServer::HandleStatus(PageEntry_t& p, PageContext_t& c) output = ExecuteCommand("stat"); c.printf("%s", _html(output)); output = ExecuteCommand("location status"); - c.printf("%s", _html(output)); + c.printf("%s", _html(output)); c.panel_end( "