Files
esphome-dev/esphome/components/prometheus/prometheus_handler.cpp
T
Otto Winter ac0d921413 ESP-IDF support and generic target platforms (#2303)
* Socket refactor and SSL

* esp-idf temp

* Fixes

* Echo component and noise

* Add noise API transport support

* Updates

* ESP-IDF

* Complete

* Fixes

* Fixes

* Versions update

* New i2c APIs

* Complete i2c refactor

* SPI migration

* Revert ESP Preferences migration, too complex for now

* OTA support

* Remove echo again

* Remove ssl again

* GPIOFlags updates

* Rename esphal and ICACHE_RAM_ATTR

* Make ESP32 arduino compilable again

* Fix GPIO flags

* Complete pin registry refactor and fixes

* Fixes to make test1 compile

* Remove sdkconfig file

* Ignore sdkconfig file

* Fixes in reviewing

* Make test2 compile

* Make test4 compile

* Make test5 compile

* Run clang-format

* Fix lint errors

* Use esp-idf APIs instead of btStart

* Another round of fixes

* Start implementing ESP8266

* Make test3 compile

* Guard esp8266 code

* Lint

* Reformat

* Fixes

* Fixes v2

* more fixes

* ESP-IDF tidy target

* Convert ARDUINO_ARCH_ESPxx

* Update WiFiSignalSensor

* Update time ifdefs

* OTA needs millis from hal

* RestartSwitch needs delay from hal

* ESP-IDF Uart

* Fix OTA blank password

* Allow setting sdkconfig

* Fix idf partitions and allow setting sdkconfig from yaml

* Re-add read/write compat APIs and fix esp8266 uart

* Fix esp8266 store log strings in flash

* Fix ESP32 arduino preferences not initialized

* Update ifdefs

* Change how sdkconfig change is detected

* Add checks to ci-custom and fix them

* Run clang-format

* Add esp-idf clang-tidy target and fix errors

* Fixes from clang-tidy idf round 2

* Fixes from compiling tests with esp-idf

* Run clang-format

* Switch test5.yaml to esp-idf

* Implement ESP8266 Preferences

* Lint

* Re-do PIO package version selection a bit

* Fix arduinoespressif32 package version

* Fix unit tests

* Lint

* Lint fixes

* Fix readv/writev not defined

* Fix graphing component

* Re-add all old options from core/config.py

Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
2021-09-20 11:47:51 +02:00

317 lines
10 KiB
C++

#ifdef USE_ARDUINO
#include "prometheus_handler.h"
#include "esphome/core/application.h"
namespace esphome {
namespace prometheus {
void PrometheusHandler::handleRequest(AsyncWebServerRequest *req) {
AsyncResponseStream *stream = req->beginResponseStream("text/plain");
#ifdef USE_SENSOR
this->sensor_type_(stream);
for (auto *obj : App.get_sensors())
this->sensor_row_(stream, obj);
#endif
#ifdef USE_BINARY_SENSOR
this->binary_sensor_type_(stream);
for (auto *obj : App.get_binary_sensors())
this->binary_sensor_row_(stream, obj);
#endif
#ifdef USE_FAN
this->fan_type_(stream);
for (auto *obj : App.get_fans())
this->fan_row_(stream, obj);
#endif
#ifdef USE_LIGHT
this->light_type_(stream);
for (auto *obj : App.get_lights())
this->light_row_(stream, obj);
#endif
#ifdef USE_COVER
this->cover_type_(stream);
for (auto *obj : App.get_covers())
this->cover_row_(stream, obj);
#endif
#ifdef USE_SWITCH
this->switch_type_(stream);
for (auto *obj : App.get_switches())
this->switch_row_(stream, obj);
#endif
req->send(stream);
}
// Type-specific implementation
#ifdef USE_SENSOR
void PrometheusHandler::sensor_type_(AsyncResponseStream *stream) {
stream->print(F("#TYPE esphome_sensor_value GAUGE\n"));
stream->print(F("#TYPE esphome_sensor_failed GAUGE\n"));
}
void PrometheusHandler::sensor_row_(AsyncResponseStream *stream, sensor::Sensor *obj) {
if (obj->is_internal())
return;
if (!std::isnan(obj->state)) {
// We have a valid value, output this value
stream->print(F("esphome_sensor_failed{id=\""));
stream->print(obj->get_object_id().c_str());
stream->print(F("\",name=\""));
stream->print(obj->get_name().c_str());
stream->print(F("\"} 0\n"));
// Data itself
stream->print(F("esphome_sensor_value{id=\""));
stream->print(obj->get_object_id().c_str());
stream->print(F("\",name=\""));
stream->print(obj->get_name().c_str());
stream->print(F("\",unit=\""));
stream->print(obj->get_unit_of_measurement().c_str());
stream->print(F("\"} "));
stream->print(value_accuracy_to_string(obj->state, obj->get_accuracy_decimals()).c_str());
stream->print('\n');
} else {
// Invalid state
stream->print(F("esphome_sensor_failed{id=\""));
stream->print(obj->get_object_id().c_str());
stream->print(F("\",name=\""));
stream->print(obj->get_name().c_str());
stream->print(F("\"} 1\n"));
}
}
#endif
// Type-specific implementation
#ifdef USE_BINARY_SENSOR
void PrometheusHandler::binary_sensor_type_(AsyncResponseStream *stream) {
stream->print(F("#TYPE esphome_binary_sensor_value GAUGE\n"));
stream->print(F("#TYPE esphome_binary_sensor_failed GAUGE\n"));
}
void PrometheusHandler::binary_sensor_row_(AsyncResponseStream *stream, binary_sensor::BinarySensor *obj) {
if (obj->is_internal())
return;
if (obj->has_state()) {
// We have a valid value, output this value
stream->print(F("esphome_binary_sensor_failed{id=\""));
stream->print(obj->get_object_id().c_str());
stream->print(F("\",name=\""));
stream->print(obj->get_name().c_str());
stream->print(F("\"} 0\n"));
// Data itself
stream->print(F("esphome_binary_sensor_value{id=\""));
stream->print(obj->get_object_id().c_str());
stream->print(F("\",name=\""));
stream->print(obj->get_name().c_str());
stream->print(F("\"} "));
stream->print(obj->state);
stream->print('\n');
} else {
// Invalid state
stream->print(F("esphome_binary_sensor_failed{id=\""));
stream->print(obj->get_object_id().c_str());
stream->print(F("\",name=\""));
stream->print(obj->get_name().c_str());
stream->print(F("\"} 1\n"));
}
}
#endif
#ifdef USE_FAN
void PrometheusHandler::fan_type_(AsyncResponseStream *stream) {
stream->print(F("#TYPE esphome_fan_value GAUGE\n"));
stream->print(F("#TYPE esphome_fan_failed GAUGE\n"));
stream->print(F("#TYPE esphome_fan_speed GAUGE\n"));
stream->print(F("#TYPE esphome_fan_oscillation GAUGE\n"));
}
void PrometheusHandler::fan_row_(AsyncResponseStream *stream, fan::FanState *obj) {
if (obj->is_internal())
return;
stream->print(F("esphome_fan_failed{id=\""));
stream->print(obj->get_object_id().c_str());
stream->print(F("\",name=\""));
stream->print(obj->get_name().c_str());
stream->print(F("\"} 0\n"));
// Data itself
stream->print(F("esphome_fan_value{id=\""));
stream->print(obj->get_object_id().c_str());
stream->print(F("\",name=\""));
stream->print(obj->get_name().c_str());
stream->print(F("\"} "));
stream->print(obj->state);
stream->print('\n');
// Speed if available
if (obj->get_traits().supports_speed()) {
stream->print(F("esphome_fan_speed{id=\""));
stream->print(obj->get_object_id().c_str());
stream->print(F("\",name=\""));
stream->print(obj->get_name().c_str());
stream->print(F("\"} "));
stream->print(obj->speed);
stream->print('\n');
}
// Oscillation if available
if (obj->get_traits().supports_oscillation()) {
stream->print(F("esphome_fan_oscillation{id=\""));
stream->print(obj->get_object_id().c_str());
stream->print(F("\",name=\""));
stream->print(obj->get_name().c_str());
stream->print(F("\"} "));
stream->print(obj->oscillating);
stream->print('\n');
}
}
#endif
#ifdef USE_LIGHT
void PrometheusHandler::light_type_(AsyncResponseStream *stream) {
stream->print(F("#TYPE esphome_light_state GAUGE\n"));
stream->print(F("#TYPE esphome_light_color GAUGE\n"));
stream->print(F("#TYPE esphome_light_effect_active GAUGE\n"));
}
void PrometheusHandler::light_row_(AsyncResponseStream *stream, light::LightState *obj) {
if (obj->is_internal())
return;
// State
stream->print(F("esphome_light_state{id=\""));
stream->print(obj->get_object_id().c_str());
stream->print(F("\",name=\""));
stream->print(obj->get_name().c_str());
stream->print(F("\"} "));
stream->print(obj->remote_values.is_on());
stream->print(F("\n"));
// Brightness and RGBW
light::LightColorValues color = obj->current_values;
float brightness, r, g, b, w;
color.as_brightness(&brightness);
color.as_rgbw(&r, &g, &b, &w);
stream->print(F("esphome_light_color{id=\""));
stream->print(obj->get_object_id().c_str());
stream->print(F("\",name=\""));
stream->print(obj->get_name().c_str());
stream->print(F("\",channel=\"brightness\"} "));
stream->print(brightness);
stream->print(F("\n"));
stream->print(F("esphome_light_color{id=\""));
stream->print(obj->get_object_id().c_str());
stream->print(F("\",name=\""));
stream->print(obj->get_name().c_str());
stream->print(F("\",channel=\"r\"} "));
stream->print(r);
stream->print(F("\n"));
stream->print(F("esphome_light_color{id=\""));
stream->print(obj->get_object_id().c_str());
stream->print(F("\",name=\""));
stream->print(obj->get_name().c_str());
stream->print(F("\",channel=\"g\"} "));
stream->print(g);
stream->print(F("\n"));
stream->print(F("esphome_light_color{id=\""));
stream->print(obj->get_object_id().c_str());
stream->print(F("\",name=\""));
stream->print(obj->get_name().c_str());
stream->print(F("\",channel=\"b\"} "));
stream->print(b);
stream->print(F("\n"));
stream->print(F("esphome_light_color{id=\""));
stream->print(obj->get_object_id().c_str());
stream->print(F("\",name=\""));
stream->print(obj->get_name().c_str());
stream->print(F("\",channel=\"w\"} "));
stream->print(w);
stream->print(F("\n"));
// Effect
std::string effect = obj->get_effect_name();
if (effect == "None") {
stream->print(F("esphome_light_effect_active{id=\""));
stream->print(obj->get_object_id().c_str());
stream->print(F("\",name=\""));
stream->print(obj->get_name().c_str());
stream->print(F("\",effect=\"None\"} 0\n"));
} else {
stream->print(F("esphome_light_effect_active{id=\""));
stream->print(obj->get_object_id().c_str());
stream->print(F("\",name=\""));
stream->print(obj->get_name().c_str());
stream->print(F("\",effect=\""));
stream->print(effect.c_str());
stream->print(F("\"} 1\n"));
}
}
#endif
#ifdef USE_COVER
void PrometheusHandler::cover_type_(AsyncResponseStream *stream) {
stream->print(F("#TYPE esphome_cover_value GAUGE\n"));
stream->print(F("#TYPE esphome_cover_failed GAUGE\n"));
}
void PrometheusHandler::cover_row_(AsyncResponseStream *stream, cover::Cover *obj) {
if (obj->is_internal())
return;
if (!std::isnan(obj->position)) {
// We have a valid value, output this value
stream->print(F("esphome_cover_failed{id=\""));
stream->print(obj->get_object_id().c_str());
stream->print(F("\",name=\""));
stream->print(obj->get_name().c_str());
stream->print(F("\"} 0\n"));
// Data itself
stream->print(F("esphome_cover_value{id=\""));
stream->print(obj->get_object_id().c_str());
stream->print(F("\",name=\""));
stream->print(obj->get_name().c_str());
stream->print(F("\"} "));
stream->print(obj->position);
stream->print('\n');
if (obj->get_traits().get_supports_tilt()) {
stream->print(F("esphome_cover_tilt{id=\""));
stream->print(obj->get_object_id().c_str());
stream->print(F("\",name=\""));
stream->print(obj->get_name().c_str());
stream->print(F("\"} "));
stream->print(obj->tilt);
stream->print('\n');
}
} else {
// Invalid state
stream->print(F("esphome_cover_failed{id=\""));
stream->print(obj->get_object_id().c_str());
stream->print(F("\",name=\""));
stream->print(obj->get_name().c_str());
stream->print(F("\"} 1\n"));
}
}
#endif
#ifdef USE_SWITCH
void PrometheusHandler::switch_type_(AsyncResponseStream *stream) {
stream->print(F("#TYPE esphome_switch_value GAUGE\n"));
stream->print(F("#TYPE esphome_switch_failed GAUGE\n"));
}
void PrometheusHandler::switch_row_(AsyncResponseStream *stream, switch_::Switch *obj) {
if (obj->is_internal())
return;
stream->print(F("esphome_switch_failed{id=\""));
stream->print(obj->get_object_id().c_str());
stream->print(F("\",name=\""));
stream->print(obj->get_name().c_str());
stream->print(F("\"} 0\n"));
// Data itself
stream->print(F("esphome_switch_value{id=\""));
stream->print(obj->get_object_id().c_str());
stream->print(F("\",name=\""));
stream->print(obj->get_name().c_str());
stream->print(F("\"} "));
stream->print(obj->state);
stream->print('\n');
}
#endif
} // namespace prometheus
} // namespace esphome
#endif // USE_ARDUINO