mirror of
https://github.com/esphome/esphome.git
synced 2025-10-04 11:02:19 +01:00
Cleanup web server prometheus integration (#1192)
This commit is contained in:
22
esphome/components/prometheus/__init__.py
Normal file
22
esphome/components/prometheus/__init__.py
Normal file
@@ -0,0 +1,22 @@
|
||||
import esphome.config_validation as cv
|
||||
import esphome.codegen as cg
|
||||
from esphome.const import CONF_ID
|
||||
from esphome.components.web_server_base import CONF_WEB_SERVER_BASE_ID
|
||||
from esphome.components import web_server_base
|
||||
|
||||
AUTO_LOAD = ['web_server_base']
|
||||
|
||||
prometheus_ns = cg.esphome_ns.namespace('prometheus')
|
||||
PrometheusHandler = prometheus_ns.class_('PrometheusHandler', cg.Component)
|
||||
|
||||
CONFIG_SCHEMA = cv.Schema({
|
||||
cv.GenerateID(): cv.declare_id(PrometheusHandler),
|
||||
cv.GenerateID(CONF_WEB_SERVER_BASE_ID): cv.use_id(web_server_base.WebServerBase),
|
||||
}).extend(cv.COMPONENT_SCHEMA)
|
||||
|
||||
|
||||
def to_code(config):
|
||||
paren = yield cg.get_variable(config[CONF_WEB_SERVER_BASE_ID])
|
||||
|
||||
var = cg.new_Pvariable(config[CONF_ID], paren)
|
||||
yield cg.register_component(var, config)
|
312
esphome/components/prometheus/prometheus_handler.cpp
Normal file
312
esphome/components/prometheus/prometheus_handler.cpp
Normal file
@@ -0,0 +1,312 @@
|
||||
#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 (!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 (!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
|
77
esphome/components/prometheus/prometheus_handler.h
Normal file
77
esphome/components/prometheus/prometheus_handler.h
Normal file
@@ -0,0 +1,77 @@
|
||||
#pragma once
|
||||
|
||||
#include "esphome/components/web_server_base/web_server_base.h"
|
||||
#include "esphome/core/controller.h"
|
||||
#include "esphome/core/component.h"
|
||||
|
||||
namespace esphome {
|
||||
namespace prometheus {
|
||||
|
||||
class PrometheusHandler : public AsyncWebHandler, public Component {
|
||||
public:
|
||||
PrometheusHandler(web_server_base::WebServerBase *base) : base_(base) {}
|
||||
|
||||
bool canHandle(AsyncWebServerRequest *request) override {
|
||||
if (request->method() == HTTP_GET) {
|
||||
if (request->url() == "/metrics")
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void handleRequest(AsyncWebServerRequest *req) override;
|
||||
|
||||
void setup() override {
|
||||
this->base_->init();
|
||||
this->base_->add_handler(this);
|
||||
}
|
||||
|
||||
protected:
|
||||
#ifdef USE_SENSOR
|
||||
/// Return the type for prometheus
|
||||
void sensor_type_(AsyncResponseStream *stream);
|
||||
/// Return the sensor state as prometheus data point
|
||||
void sensor_row_(AsyncResponseStream *stream, sensor::Sensor *obj);
|
||||
#endif
|
||||
|
||||
#ifdef USE_BINARY_SENSOR
|
||||
/// Return the type for prometheus
|
||||
void binary_sensor_type_(AsyncResponseStream *stream);
|
||||
/// Return the sensor state as prometheus data point
|
||||
void binary_sensor_row_(AsyncResponseStream *stream, binary_sensor::BinarySensor *obj);
|
||||
#endif
|
||||
|
||||
#ifdef USE_FAN
|
||||
/// Return the type for prometheus
|
||||
void fan_type_(AsyncResponseStream *stream);
|
||||
/// Return the sensor state as prometheus data point
|
||||
void fan_row_(AsyncResponseStream *stream, fan::FanState *obj);
|
||||
#endif
|
||||
|
||||
#ifdef USE_LIGHT
|
||||
/// Return the type for prometheus
|
||||
void light_type_(AsyncResponseStream *stream);
|
||||
/// Return the Light Values state as prometheus data point
|
||||
void light_row_(AsyncResponseStream *stream, light::LightState *obj);
|
||||
#endif
|
||||
|
||||
#ifdef USE_COVER
|
||||
/// Return the type for prometheus
|
||||
void cover_type_(AsyncResponseStream *stream);
|
||||
/// Return the switch Values state as prometheus data point
|
||||
void cover_row_(AsyncResponseStream *stream, cover::Cover *obj);
|
||||
#endif
|
||||
|
||||
#ifdef USE_SWITCH
|
||||
/// Return the type for prometheus
|
||||
void switch_type_(AsyncResponseStream *stream);
|
||||
/// Return the switch Values state as prometheus data point
|
||||
void switch_row_(AsyncResponseStream *stream, switch_::Switch *obj);
|
||||
#endif
|
||||
|
||||
web_server_base::WebServerBase *base_;
|
||||
};
|
||||
|
||||
} // namespace prometheus
|
||||
} // namespace esphome
|
Reference in New Issue
Block a user