From c50e33f531aed5536267c1633d37ac6a98a5fcfe Mon Sep 17 00:00:00 2001 From: Thomas Rupprecht Date: Thu, 15 May 2025 12:07:41 +0200 Subject: [PATCH] [gps] update lib, improve code/tests/config (#8768) --- CODEOWNERS | 2 +- esphome/components/gps/__init__.py | 53 +++++++++++++++++++++--------- esphome/components/gps/gps.cpp | 50 ++++++++++++++++++---------- esphome/components/gps/gps.h | 31 ++++++++--------- platformio.ini | 2 +- tests/components/gps/common.yaml | 14 ++++++++ 6 files changed, 102 insertions(+), 50 deletions(-) diff --git a/CODEOWNERS b/CODEOWNERS index ddd0494a3c..a6e08f225d 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -169,7 +169,7 @@ esphome/components/gp2y1010au0f/* @zry98 esphome/components/gp8403/* @jesserockz esphome/components/gpio/* @esphome/core esphome/components/gpio/one_wire/* @ssieb -esphome/components/gps/* @coogle +esphome/components/gps/* @coogle @ximex esphome/components/graph/* @synco esphome/components/graphical_display_menu/* @MrMDavidson esphome/components/gree/* @orestismers diff --git a/esphome/components/gps/__init__.py b/esphome/components/gps/__init__.py index 88e6f0fd9b..7ccd82dec3 100644 --- a/esphome/components/gps/__init__.py +++ b/esphome/components/gps/__init__.py @@ -9,23 +9,32 @@ from esphome.const import ( CONF_LONGITUDE, CONF_SATELLITES, CONF_SPEED, + DEVICE_CLASS_SPEED, STATE_CLASS_MEASUREMENT, UNIT_DEGREES, UNIT_KILOMETER_PER_HOUR, UNIT_METER, ) +CONF_GPS_ID = "gps_id" +CONF_HDOP = "hdop" + +ICON_ALTIMETER = "mdi:altimeter" +ICON_COMPASS = "mdi:compass" +ICON_LATITUDE = "mdi:latitude" +ICON_LONGITUDE = "mdi:longitude" +ICON_SATELLITE = "mdi:satellite-variant" +ICON_SPEEDOMETER = "mdi:speedometer" + DEPENDENCIES = ["uart"] AUTO_LOAD = ["sensor"] -CODEOWNERS = ["@coogle"] +CODEOWNERS = ["@coogle", "@ximex"] gps_ns = cg.esphome_ns.namespace("gps") GPS = gps_ns.class_("GPS", cg.Component, uart.UARTDevice) GPSListener = gps_ns.class_("GPSListener") -CONF_GPS_ID = "gps_id" -CONF_HDOP = "hdop" MULTI_CONF = True CONFIG_SCHEMA = cv.All( cv.Schema( @@ -33,25 +42,37 @@ CONFIG_SCHEMA = cv.All( cv.GenerateID(): cv.declare_id(GPS), cv.Optional(CONF_LATITUDE): sensor.sensor_schema( unit_of_measurement=UNIT_DEGREES, + icon=ICON_LATITUDE, accuracy_decimals=6, + state_class=STATE_CLASS_MEASUREMENT, ), cv.Optional(CONF_LONGITUDE): sensor.sensor_schema( unit_of_measurement=UNIT_DEGREES, + icon=ICON_LONGITUDE, accuracy_decimals=6, + state_class=STATE_CLASS_MEASUREMENT, ), cv.Optional(CONF_SPEED): sensor.sensor_schema( unit_of_measurement=UNIT_KILOMETER_PER_HOUR, + icon=ICON_SPEEDOMETER, accuracy_decimals=3, + device_class=DEVICE_CLASS_SPEED, + state_class=STATE_CLASS_MEASUREMENT, ), cv.Optional(CONF_COURSE): sensor.sensor_schema( unit_of_measurement=UNIT_DEGREES, + icon=ICON_COMPASS, accuracy_decimals=2, + state_class=STATE_CLASS_MEASUREMENT, ), cv.Optional(CONF_ALTITUDE): sensor.sensor_schema( unit_of_measurement=UNIT_METER, + icon=ICON_ALTIMETER, accuracy_decimals=2, + state_class=STATE_CLASS_MEASUREMENT, ), cv.Optional(CONF_SATELLITES): sensor.sensor_schema( + icon=ICON_SATELLITE, accuracy_decimals=0, state_class=STATE_CLASS_MEASUREMENT, ), @@ -73,28 +94,28 @@ async def to_code(config): await cg.register_component(var, config) await uart.register_uart_device(var, config) - if CONF_LATITUDE in config: - sens = await sensor.new_sensor(config[CONF_LATITUDE]) + if latitude_config := config.get(CONF_LATITUDE): + sens = await sensor.new_sensor(latitude_config) cg.add(var.set_latitude_sensor(sens)) - if CONF_LONGITUDE in config: - sens = await sensor.new_sensor(config[CONF_LONGITUDE]) + if longitude_config := config.get(CONF_LONGITUDE): + sens = await sensor.new_sensor(longitude_config) cg.add(var.set_longitude_sensor(sens)) - if CONF_SPEED in config: - sens = await sensor.new_sensor(config[CONF_SPEED]) + if speed_config := config.get(CONF_SPEED): + sens = await sensor.new_sensor(speed_config) cg.add(var.set_speed_sensor(sens)) - if CONF_COURSE in config: - sens = await sensor.new_sensor(config[CONF_COURSE]) + if course_config := config.get(CONF_COURSE): + sens = await sensor.new_sensor(course_config) cg.add(var.set_course_sensor(sens)) - if CONF_ALTITUDE in config: - sens = await sensor.new_sensor(config[CONF_ALTITUDE]) + if altitude_config := config.get(CONF_ALTITUDE): + sens = await sensor.new_sensor(altitude_config) cg.add(var.set_altitude_sensor(sens)) - if CONF_SATELLITES in config: - sens = await sensor.new_sensor(config[CONF_SATELLITES]) + if satellites_config := config.get(CONF_SATELLITES): + sens = await sensor.new_sensor(satellites_config) cg.add(var.set_satellites_sensor(sens)) if hdop_config := config.get(CONF_HDOP): @@ -102,4 +123,4 @@ async def to_code(config): cg.add(var.set_hdop_sensor(sens)) # https://platformio.org/lib/show/1655/TinyGPSPlus - cg.add_library("mikalhart/TinyGPSPlus", "1.0.2") + cg.add_library("mikalhart/TinyGPSPlus", "1.1.0") diff --git a/esphome/components/gps/gps.cpp b/esphome/components/gps/gps.cpp index e54afdb07e..9dcb351b39 100644 --- a/esphome/components/gps/gps.cpp +++ b/esphome/components/gps/gps.cpp @@ -10,6 +10,17 @@ static const char *const TAG = "gps"; TinyGPSPlus &GPSListener::get_tiny_gps() { return this->parent_->get_tiny_gps(); } +void GPS::dump_config() { + ESP_LOGCONFIG(TAG, "GPS:"); + LOG_SENSOR(" ", "Latitude", this->latitude_sensor_); + LOG_SENSOR(" ", "Longitude", this->longitude_sensor_); + LOG_SENSOR(" ", "Speed", this->speed_sensor_); + LOG_SENSOR(" ", "Course", this->course_sensor_); + LOG_SENSOR(" ", "Altitude", this->altitude_sensor_); + LOG_SENSOR(" ", "Satellites", this->satellites_sensor_); + LOG_SENSOR(" ", "HDOP", this->hdop_sensor_); +} + void GPS::update() { if (this->latitude_sensor_ != nullptr) this->latitude_sensor_->publish_state(this->latitude_); @@ -34,40 +45,45 @@ void GPS::update() { } void GPS::loop() { - while (this->available() && !this->has_time_) { + while (this->available() > 0 && !this->has_time_) { if (this->tiny_gps_.encode(this->read())) { - if (tiny_gps_.location.isUpdated()) { - this->latitude_ = tiny_gps_.location.lat(); - this->longitude_ = tiny_gps_.location.lng(); + if (this->tiny_gps_.location.isUpdated()) { + this->latitude_ = this->tiny_gps_.location.lat(); + this->longitude_ = this->tiny_gps_.location.lng(); ESP_LOGD(TAG, "Location:"); - ESP_LOGD(TAG, " Lat: %f", this->latitude_); - ESP_LOGD(TAG, " Lon: %f", this->longitude_); + ESP_LOGD(TAG, " Lat: %.6f °", this->latitude_); + ESP_LOGD(TAG, " Lon: %.6f °", this->longitude_); } - if (tiny_gps_.speed.isUpdated()) { - this->speed_ = tiny_gps_.speed.kmph(); + if (this->tiny_gps_.speed.isUpdated()) { + this->speed_ = this->tiny_gps_.speed.kmph(); ESP_LOGD(TAG, "Speed: %.3f km/h", this->speed_); } - if (tiny_gps_.course.isUpdated()) { - this->course_ = tiny_gps_.course.deg(); + + if (this->tiny_gps_.course.isUpdated()) { + this->course_ = this->tiny_gps_.course.deg(); ESP_LOGD(TAG, "Course: %.2f °", this->course_); } - if (tiny_gps_.altitude.isUpdated()) { - this->altitude_ = tiny_gps_.altitude.meters(); + + if (this->tiny_gps_.altitude.isUpdated()) { + this->altitude_ = this->tiny_gps_.altitude.meters(); ESP_LOGD(TAG, "Altitude: %.2f m", this->altitude_); } - if (tiny_gps_.satellites.isUpdated()) { - this->satellites_ = tiny_gps_.satellites.value(); + + if (this->tiny_gps_.satellites.isUpdated()) { + this->satellites_ = this->tiny_gps_.satellites.value(); ESP_LOGD(TAG, "Satellites: %d", this->satellites_); } - if (tiny_gps_.hdop.isUpdated()) { - this->hdop_ = tiny_gps_.hdop.hdop(); + + if (this->tiny_gps_.hdop.isUpdated()) { + this->hdop_ = this->tiny_gps_.hdop.hdop(); ESP_LOGD(TAG, "HDOP: %.3f", this->hdop_); } - for (auto *listener : this->listeners_) + for (auto *listener : this->listeners_) { listener->on_update(this->tiny_gps_); + } } } } diff --git a/esphome/components/gps/gps.h b/esphome/components/gps/gps.h index a400820738..7bc23ed1e0 100644 --- a/esphome/components/gps/gps.h +++ b/esphome/components/gps/gps.h @@ -5,7 +5,7 @@ #include "esphome/core/component.h" #include "esphome/components/uart/uart.h" #include "esphome/components/sensor/sensor.h" -#include +#include #include @@ -27,13 +27,13 @@ class GPSListener { class GPS : public PollingComponent, public uart::UARTDevice { public: - void set_latitude_sensor(sensor::Sensor *latitude_sensor) { latitude_sensor_ = latitude_sensor; } - void set_longitude_sensor(sensor::Sensor *longitude_sensor) { longitude_sensor_ = longitude_sensor; } - void set_speed_sensor(sensor::Sensor *speed_sensor) { speed_sensor_ = speed_sensor; } - void set_course_sensor(sensor::Sensor *course_sensor) { course_sensor_ = course_sensor; } - void set_altitude_sensor(sensor::Sensor *altitude_sensor) { altitude_sensor_ = altitude_sensor; } - void set_satellites_sensor(sensor::Sensor *satellites_sensor) { satellites_sensor_ = satellites_sensor; } - void set_hdop_sensor(sensor::Sensor *hdop_sensor) { hdop_sensor_ = hdop_sensor; } + void set_latitude_sensor(sensor::Sensor *latitude_sensor) { this->latitude_sensor_ = latitude_sensor; } + void set_longitude_sensor(sensor::Sensor *longitude_sensor) { this->longitude_sensor_ = longitude_sensor; } + void set_speed_sensor(sensor::Sensor *speed_sensor) { this->speed_sensor_ = speed_sensor; } + void set_course_sensor(sensor::Sensor *course_sensor) { this->course_sensor_ = course_sensor; } + void set_altitude_sensor(sensor::Sensor *altitude_sensor) { this->altitude_sensor_ = altitude_sensor; } + void set_satellites_sensor(sensor::Sensor *satellites_sensor) { this->satellites_sensor_ = satellites_sensor; } + void set_hdop_sensor(sensor::Sensor *hdop_sensor) { this->hdop_sensor_ = hdop_sensor; } void register_listener(GPSListener *listener) { listener->parent_ = this; @@ -41,19 +41,20 @@ class GPS : public PollingComponent, public uart::UARTDevice { } float get_setup_priority() const override { return setup_priority::HARDWARE; } + void dump_config() override; void loop() override; void update() override; TinyGPSPlus &get_tiny_gps() { return this->tiny_gps_; } protected: - float latitude_ = NAN; - float longitude_ = NAN; - float speed_ = NAN; - float course_ = NAN; - float altitude_ = NAN; - int satellites_ = 0; - double hdop_ = NAN; + float latitude_{NAN}; + float longitude_{NAN}; + float speed_{NAN}; + float course_{NAN}; + float altitude_{NAN}; + uint16_t satellites_{0}; + float hdop_{NAN}; sensor::Sensor *latitude_sensor_{nullptr}; sensor::Sensor *longitude_sensor_{nullptr}; diff --git a/platformio.ini b/platformio.ini index ccfd52c3ca..292188c6fa 100644 --- a/platformio.ini +++ b/platformio.ini @@ -64,7 +64,7 @@ lib_deps = heman/AsyncMqttClient-esphome@1.0.0 ; mqtt esphome/ESPAsyncWebServer-esphome@3.3.0 ; web_server_base fastled/FastLED@3.9.16 ; fastled_base - mikalhart/TinyGPSPlus@1.0.2 ; gps + mikalhart/TinyGPSPlus@1.1.0 ; gps freekode/TM1651@1.0.1 ; tm1651 glmnet/Dsmr@0.7 ; dsmr rweather/Crypto@0.4.0 ; dsmr diff --git a/tests/components/gps/common.yaml b/tests/components/gps/common.yaml index fc8228c909..53dc67e457 100644 --- a/tests/components/gps/common.yaml +++ b/tests/components/gps/common.yaml @@ -6,6 +6,20 @@ uart: parity: EVEN gps: + latitude: + name: "Latitude" + longitude: + name: "Longitude" + altitude: + name: "Altitude" + speed: + name: "Speed" + course: + name: "Course" + satellites: + name: "Satellites" + hdop: + name: "HDOP" time: - platform: gps