ESPHome  2024.9.0
prometheus_handler.cpp
Go to the documentation of this file.
1 #include "prometheus_handler.h"
2 #ifdef USE_NETWORK
4 
5 namespace esphome {
6 namespace prometheus {
7 
8 void PrometheusHandler::handleRequest(AsyncWebServerRequest *req) {
9  AsyncResponseStream *stream = req->beginResponseStream("text/plain; version=0.0.4; charset=utf-8");
10 
11 #ifdef USE_SENSOR
12  this->sensor_type_(stream);
13  for (auto *obj : App.get_sensors())
14  this->sensor_row_(stream, obj);
15 #endif
16 
17 #ifdef USE_BINARY_SENSOR
18  this->binary_sensor_type_(stream);
19  for (auto *obj : App.get_binary_sensors())
20  this->binary_sensor_row_(stream, obj);
21 #endif
22 
23 #ifdef USE_FAN
24  this->fan_type_(stream);
25  for (auto *obj : App.get_fans())
26  this->fan_row_(stream, obj);
27 #endif
28 
29 #ifdef USE_LIGHT
30  this->light_type_(stream);
31  for (auto *obj : App.get_lights())
32  this->light_row_(stream, obj);
33 #endif
34 
35 #ifdef USE_COVER
36  this->cover_type_(stream);
37  for (auto *obj : App.get_covers())
38  this->cover_row_(stream, obj);
39 #endif
40 
41 #ifdef USE_SWITCH
42  this->switch_type_(stream);
43  for (auto *obj : App.get_switches())
44  this->switch_row_(stream, obj);
45 #endif
46 
47 #ifdef USE_LOCK
48  this->lock_type_(stream);
49  for (auto *obj : App.get_locks())
50  this->lock_row_(stream, obj);
51 #endif
52 
53  req->send(stream);
54 }
55 
57  auto item = relabel_map_id_.find(obj);
58  return item == relabel_map_id_.end() ? obj->get_object_id() : item->second;
59 }
60 
62  auto item = relabel_map_name_.find(obj);
63  return item == relabel_map_name_.end() ? obj->get_name() : item->second;
64 }
65 
66 // Type-specific implementation
67 #ifdef USE_SENSOR
68 void PrometheusHandler::sensor_type_(AsyncResponseStream *stream) {
69  stream->print(F("#TYPE esphome_sensor_value gauge\n"));
70  stream->print(F("#TYPE esphome_sensor_failed gauge\n"));
71 }
72 void PrometheusHandler::sensor_row_(AsyncResponseStream *stream, sensor::Sensor *obj) {
73  if (obj->is_internal() && !this->include_internal_)
74  return;
75  if (!std::isnan(obj->state)) {
76  // We have a valid value, output this value
77  stream->print(F("esphome_sensor_failed{id=\""));
78  stream->print(relabel_id_(obj).c_str());
79  stream->print(F("\",name=\""));
80  stream->print(relabel_name_(obj).c_str());
81  stream->print(F("\"} 0\n"));
82  // Data itself
83  stream->print(F("esphome_sensor_value{id=\""));
84  stream->print(relabel_id_(obj).c_str());
85  stream->print(F("\",name=\""));
86  stream->print(relabel_name_(obj).c_str());
87  stream->print(F("\",unit=\""));
88  stream->print(obj->get_unit_of_measurement().c_str());
89  stream->print(F("\"} "));
90  stream->print(value_accuracy_to_string(obj->state, obj->get_accuracy_decimals()).c_str());
91  stream->print(F("\n"));
92  } else {
93  // Invalid state
94  stream->print(F("esphome_sensor_failed{id=\""));
95  stream->print(relabel_id_(obj).c_str());
96  stream->print(F("\",name=\""));
97  stream->print(relabel_name_(obj).c_str());
98  stream->print(F("\"} 1\n"));
99  }
100 }
101 #endif
102 
103 // Type-specific implementation
104 #ifdef USE_BINARY_SENSOR
105 void PrometheusHandler::binary_sensor_type_(AsyncResponseStream *stream) {
106  stream->print(F("#TYPE esphome_binary_sensor_value gauge\n"));
107  stream->print(F("#TYPE esphome_binary_sensor_failed gauge\n"));
108 }
110  if (obj->is_internal() && !this->include_internal_)
111  return;
112  if (obj->has_state()) {
113  // We have a valid value, output this value
114  stream->print(F("esphome_binary_sensor_failed{id=\""));
115  stream->print(relabel_id_(obj).c_str());
116  stream->print(F("\",name=\""));
117  stream->print(relabel_name_(obj).c_str());
118  stream->print(F("\"} 0\n"));
119  // Data itself
120  stream->print(F("esphome_binary_sensor_value{id=\""));
121  stream->print(relabel_id_(obj).c_str());
122  stream->print(F("\",name=\""));
123  stream->print(relabel_name_(obj).c_str());
124  stream->print(F("\"} "));
125  stream->print(obj->state);
126  stream->print(F("\n"));
127  } else {
128  // Invalid state
129  stream->print(F("esphome_binary_sensor_failed{id=\""));
130  stream->print(relabel_id_(obj).c_str());
131  stream->print(F("\",name=\""));
132  stream->print(relabel_name_(obj).c_str());
133  stream->print(F("\"} 1\n"));
134  }
135 }
136 #endif
137 
138 #ifdef USE_FAN
139 void PrometheusHandler::fan_type_(AsyncResponseStream *stream) {
140  stream->print(F("#TYPE esphome_fan_value gauge\n"));
141  stream->print(F("#TYPE esphome_fan_failed gauge\n"));
142  stream->print(F("#TYPE esphome_fan_speed gauge\n"));
143  stream->print(F("#TYPE esphome_fan_oscillation gauge\n"));
144 }
145 void PrometheusHandler::fan_row_(AsyncResponseStream *stream, fan::Fan *obj) {
146  if (obj->is_internal() && !this->include_internal_)
147  return;
148  stream->print(F("esphome_fan_failed{id=\""));
149  stream->print(relabel_id_(obj).c_str());
150  stream->print(F("\",name=\""));
151  stream->print(relabel_name_(obj).c_str());
152  stream->print(F("\"} 0\n"));
153  // Data itself
154  stream->print(F("esphome_fan_value{id=\""));
155  stream->print(relabel_id_(obj).c_str());
156  stream->print(F("\",name=\""));
157  stream->print(relabel_name_(obj).c_str());
158  stream->print(F("\"} "));
159  stream->print(obj->state);
160  stream->print(F("\n"));
161  // Speed if available
162  if (obj->get_traits().supports_speed()) {
163  stream->print(F("esphome_fan_speed{id=\""));
164  stream->print(relabel_id_(obj).c_str());
165  stream->print(F("\",name=\""));
166  stream->print(relabel_name_(obj).c_str());
167  stream->print(F("\"} "));
168  stream->print(obj->speed);
169  stream->print(F("\n"));
170  }
171  // Oscillation if available
172  if (obj->get_traits().supports_oscillation()) {
173  stream->print(F("esphome_fan_oscillation{id=\""));
174  stream->print(relabel_id_(obj).c_str());
175  stream->print(F("\",name=\""));
176  stream->print(relabel_name_(obj).c_str());
177  stream->print(F("\"} "));
178  stream->print(obj->oscillating);
179  stream->print(F("\n"));
180  }
181 }
182 #endif
183 
184 #ifdef USE_LIGHT
185 void PrometheusHandler::light_type_(AsyncResponseStream *stream) {
186  stream->print(F("#TYPE esphome_light_state gauge\n"));
187  stream->print(F("#TYPE esphome_light_color gauge\n"));
188  stream->print(F("#TYPE esphome_light_effect_active gauge\n"));
189 }
190 void PrometheusHandler::light_row_(AsyncResponseStream *stream, light::LightState *obj) {
191  if (obj->is_internal() && !this->include_internal_)
192  return;
193  // State
194  stream->print(F("esphome_light_state{id=\""));
195  stream->print(relabel_id_(obj).c_str());
196  stream->print(F("\",name=\""));
197  stream->print(relabel_name_(obj).c_str());
198  stream->print(F("\"} "));
199  stream->print(obj->remote_values.is_on());
200  stream->print(F("\n"));
201  // Brightness and RGBW
203  float brightness, r, g, b, w;
204  color.as_brightness(&brightness);
205  color.as_rgbw(&r, &g, &b, &w);
206  stream->print(F("esphome_light_color{id=\""));
207  stream->print(relabel_id_(obj).c_str());
208  stream->print(F("\",name=\""));
209  stream->print(relabel_name_(obj).c_str());
210  stream->print(F("\",channel=\"brightness\"} "));
211  stream->print(brightness);
212  stream->print(F("\n"));
213  stream->print(F("esphome_light_color{id=\""));
214  stream->print(relabel_id_(obj).c_str());
215  stream->print(F("\",name=\""));
216  stream->print(relabel_name_(obj).c_str());
217  stream->print(F("\",channel=\"r\"} "));
218  stream->print(r);
219  stream->print(F("\n"));
220  stream->print(F("esphome_light_color{id=\""));
221  stream->print(relabel_id_(obj).c_str());
222  stream->print(F("\",name=\""));
223  stream->print(relabel_name_(obj).c_str());
224  stream->print(F("\",channel=\"g\"} "));
225  stream->print(g);
226  stream->print(F("\n"));
227  stream->print(F("esphome_light_color{id=\""));
228  stream->print(relabel_id_(obj).c_str());
229  stream->print(F("\",name=\""));
230  stream->print(relabel_name_(obj).c_str());
231  stream->print(F("\",channel=\"b\"} "));
232  stream->print(b);
233  stream->print(F("\n"));
234  stream->print(F("esphome_light_color{id=\""));
235  stream->print(relabel_id_(obj).c_str());
236  stream->print(F("\",name=\""));
237  stream->print(relabel_name_(obj).c_str());
238  stream->print(F("\",channel=\"w\"} "));
239  stream->print(w);
240  stream->print(F("\n"));
241  // Effect
242  std::string effect = obj->get_effect_name();
243  if (effect == "None") {
244  stream->print(F("esphome_light_effect_active{id=\""));
245  stream->print(relabel_id_(obj).c_str());
246  stream->print(F("\",name=\""));
247  stream->print(relabel_name_(obj).c_str());
248  stream->print(F("\",effect=\"None\"} 0\n"));
249  } else {
250  stream->print(F("esphome_light_effect_active{id=\""));
251  stream->print(relabel_id_(obj).c_str());
252  stream->print(F("\",name=\""));
253  stream->print(relabel_name_(obj).c_str());
254  stream->print(F("\",effect=\""));
255  stream->print(effect.c_str());
256  stream->print(F("\"} 1\n"));
257  }
258 }
259 #endif
260 
261 #ifdef USE_COVER
262 void PrometheusHandler::cover_type_(AsyncResponseStream *stream) {
263  stream->print(F("#TYPE esphome_cover_value gauge\n"));
264  stream->print(F("#TYPE esphome_cover_failed gauge\n"));
265 }
266 void PrometheusHandler::cover_row_(AsyncResponseStream *stream, cover::Cover *obj) {
267  if (obj->is_internal() && !this->include_internal_)
268  return;
269  if (!std::isnan(obj->position)) {
270  // We have a valid value, output this value
271  stream->print(F("esphome_cover_failed{id=\""));
272  stream->print(relabel_id_(obj).c_str());
273  stream->print(F("\",name=\""));
274  stream->print(relabel_name_(obj).c_str());
275  stream->print(F("\"} 0\n"));
276  // Data itself
277  stream->print(F("esphome_cover_value{id=\""));
278  stream->print(relabel_id_(obj).c_str());
279  stream->print(F("\",name=\""));
280  stream->print(relabel_name_(obj).c_str());
281  stream->print(F("\"} "));
282  stream->print(obj->position);
283  stream->print(F("\n"));
284  if (obj->get_traits().get_supports_tilt()) {
285  stream->print(F("esphome_cover_tilt{id=\""));
286  stream->print(relabel_id_(obj).c_str());
287  stream->print(F("\",name=\""));
288  stream->print(relabel_name_(obj).c_str());
289  stream->print(F("\"} "));
290  stream->print(obj->tilt);
291  stream->print(F("\n"));
292  }
293  } else {
294  // Invalid state
295  stream->print(F("esphome_cover_failed{id=\""));
296  stream->print(relabel_id_(obj).c_str());
297  stream->print(F("\",name=\""));
298  stream->print(relabel_name_(obj).c_str());
299  stream->print(F("\"} 1\n"));
300  }
301 }
302 #endif
303 
304 #ifdef USE_SWITCH
305 void PrometheusHandler::switch_type_(AsyncResponseStream *stream) {
306  stream->print(F("#TYPE esphome_switch_value gauge\n"));
307  stream->print(F("#TYPE esphome_switch_failed gauge\n"));
308 }
309 void PrometheusHandler::switch_row_(AsyncResponseStream *stream, switch_::Switch *obj) {
310  if (obj->is_internal() && !this->include_internal_)
311  return;
312  stream->print(F("esphome_switch_failed{id=\""));
313  stream->print(relabel_id_(obj).c_str());
314  stream->print(F("\",name=\""));
315  stream->print(relabel_name_(obj).c_str());
316  stream->print(F("\"} 0\n"));
317  // Data itself
318  stream->print(F("esphome_switch_value{id=\""));
319  stream->print(relabel_id_(obj).c_str());
320  stream->print(F("\",name=\""));
321  stream->print(relabel_name_(obj).c_str());
322  stream->print(F("\"} "));
323  stream->print(obj->state);
324  stream->print(F("\n"));
325 }
326 #endif
327 
328 #ifdef USE_LOCK
329 void PrometheusHandler::lock_type_(AsyncResponseStream *stream) {
330  stream->print(F("#TYPE esphome_lock_value gauge\n"));
331  stream->print(F("#TYPE esphome_lock_failed gauge\n"));
332 }
333 void PrometheusHandler::lock_row_(AsyncResponseStream *stream, lock::Lock *obj) {
334  if (obj->is_internal() && !this->include_internal_)
335  return;
336  stream->print(F("esphome_lock_failed{id=\""));
337  stream->print(relabel_id_(obj).c_str());
338  stream->print(F("\",name=\""));
339  stream->print(relabel_name_(obj).c_str());
340  stream->print(F("\"} 0\n"));
341  // Data itself
342  stream->print(F("esphome_lock_value{id=\""));
343  stream->print(relabel_id_(obj).c_str());
344  stream->print(F("\",name=\""));
345  stream->print(relabel_name_(obj).c_str());
346  stream->print(F("\"} "));
347  stream->print(obj->state);
348  stream->print(F("\n"));
349 }
350 #endif
351 
352 } // namespace prometheus
353 } // namespace esphome
354 #endif
Base class for all switches.
Definition: switch.h:39
bool state
The current on/off state of the fan.
Definition: fan.h:110
void handleRequest(AsyncWebServerRequest *req) override
This class represents the communication layer between the front-end MQTT layer and the hardware outpu...
Definition: light_state.h:34
bool oscillating
The current oscillation state of the fan.
Definition: fan.h:112
void switch_row_(AsyncResponseStream *stream, switch_::Switch *obj)
Return the switch Values state as prometheus data point.
bool is_on() const
Get the binary true/false state of these light color values.
Base class for all cover devices.
Definition: cover.h:111
std::string value_accuracy_to_string(float value, int8_t accuracy_decimals)
Create a string from a value and an accuracy in decimals.
Definition: helpers.cpp:412
LightColorValues current_values
The current values of the light as outputted to the light.
Definition: light_state.h:65
std::string get_effect_name()
Return the name of the current effect, or if no effect is active "None".
LockState state
The current reported state of the lock.
Definition: lock.h:122
virtual FanTraits get_traits()=0
std::string relabel_id_(EntityBase *obj)
const std::vector< fan::Fan * > & get_fans()
Definition: application.h:297
void switch_type_(AsyncResponseStream *stream)
Return the type for prometheus.
bool supports_oscillation() const
Return if this fan supports oscillation.
Definition: fan_traits.h:16
float tilt
The current tilt value of the cover from 0.0 to 1.0.
Definition: cover.h:124
std::string get_object_id() const
Definition: entity_base.cpp:43
virtual CoverTraits get_traits()=0
const std::vector< lock::Lock * > & get_locks()
Definition: application.h:397
float state
This member variable stores the last state that has passed through all filters.
Definition: sensor.h:131
This class represents the color state for a light object.
void light_row_(AsyncResponseStream *stream, light::LightState *obj)
Return the Light Values state as prometheus data point.
virtual bool has_state() const
Return whether this binary sensor has outputted a state.
void binary_sensor_type_(AsyncResponseStream *stream)
Return the type for prometheus.
const std::vector< switch_::Switch * > & get_switches()
Definition: application.h:257
int speed
The current fan speed level.
Definition: fan.h:114
bool is_internal() const
Definition: entity_base.cpp:22
void sensor_row_(AsyncResponseStream *stream, sensor::Sensor *obj)
Return the sensor state as prometheus data point.
std::string get_unit_of_measurement()
Get the unit of measurement, using the manual override if set.
Definition: entity_base.cpp:87
std::map< EntityBase *, std::string > relabel_map_name_
bool state
The current reported state of the binary sensor.
Definition: binary_sensor.h:61
const std::vector< sensor::Sensor * > & get_sensors()
Definition: application.h:277
Application App
Global storage of Application pointer - only one Application can exist.
void light_type_(AsyncResponseStream *stream)
Return the type for prometheus.
const std::vector< binary_sensor::BinarySensor * > & get_binary_sensors()
Definition: application.h:247
void binary_sensor_row_(AsyncResponseStream *stream, binary_sensor::BinarySensor *obj)
Return the sensor state as prometheus data point.
const std::vector< cover::Cover * > & get_covers()
Definition: application.h:307
void lock_row_(AsyncResponseStream *stream, lock::Lock *obj)
Return the lock Values state as prometheus data point.
void lock_type_(AsyncResponseStream *stream)
Return the type for prometheus.
float position
The position of the cover from 0.0 (fully closed) to 1.0 (fully open).
Definition: cover.h:122
void fan_type_(AsyncResponseStream *stream)
Return the type for prometheus.
void sensor_type_(AsyncResponseStream *stream)
Return the type for prometheus.
const std::vector< light::LightState * > & get_lights()
Definition: application.h:317
void cover_type_(AsyncResponseStream *stream)
Return the type for prometheus.
std::string relabel_name_(EntityBase *obj)
bool get_supports_tilt() const
Definition: cover_traits.h:14
Implementation of SPI Controller mode.
Definition: a01nyub.cpp:7
Base class for all binary_sensor-type classes.
Definition: binary_sensor.h:37
LightColorValues remote_values
The remote color values reported to the frontend.
Definition: light_state.h:77
void as_rgbw(float *red, float *green, float *blue, float *white, float gamma=0, bool color_interlock=false) const
Convert these light color values to an RGBW representation and write them to red, green...
int8_t get_accuracy_decimals()
Get the accuracy in decimals, using the manual override if set.
Definition: sensor.cpp:25
Base-class for all sensors.
Definition: sensor.h:57
void as_brightness(float *brightness, float gamma=0) const
Convert these light color values to a brightness-only representation and write them to brightness...
std::map< EntityBase *, std::string > relabel_map_id_
bool state
The current reported state of the binary sensor.
Definition: switch.h:53
void cover_row_(AsyncResponseStream *stream, cover::Cover *obj)
Return the switch Values state as prometheus data point.
const StringRef & get_name() const
Definition: entity_base.cpp:10
Base class for all locks.
Definition: lock.h:103
void fan_row_(AsyncResponseStream *stream, fan::Fan *obj)
Return the sensor state as prometheus data point.
bool supports_speed() const
Return if this fan supports speed modes.
Definition: fan_traits.h:20