ESPHome 2026.5.0b1
Loading...
Searching...
No Matches
prometheus_handler.cpp
Go to the documentation of this file.
2#ifdef USE_NETWORK
4
5namespace esphome::prometheus {
6
7void PrometheusHandler::handleRequest(AsyncWebServerRequest *req) {
8 AsyncResponseStream *stream = req->beginResponseStream("text/plain; version=0.0.4; charset=utf-8");
9 std::string area = App.get_area();
10 std::string node = App.get_name();
11 std::string friendly_name = App.get_friendly_name();
12
13#ifdef USE_SENSOR
14 this->sensor_type_(stream);
15 for (auto *obj : App.get_sensors())
16 this->sensor_row_(stream, obj, area, node, friendly_name);
17#endif
18
19#ifdef USE_BINARY_SENSOR
20 this->binary_sensor_type_(stream);
21 for (auto *obj : App.get_binary_sensors())
22 this->binary_sensor_row_(stream, obj, area, node, friendly_name);
23#endif
24
25#ifdef USE_FAN
26 this->fan_type_(stream);
27 for (auto *obj : App.get_fans())
28 this->fan_row_(stream, obj, area, node, friendly_name);
29#endif
30
31#ifdef USE_LIGHT
32 this->light_type_(stream);
33 for (auto *obj : App.get_lights())
34 this->light_row_(stream, obj, area, node, friendly_name);
35#endif
36
37#ifdef USE_COVER
38 this->cover_type_(stream);
39 for (auto *obj : App.get_covers())
40 this->cover_row_(stream, obj, area, node, friendly_name);
41#endif
42
43#ifdef USE_SWITCH
44 this->switch_type_(stream);
45 for (auto *obj : App.get_switches())
46 this->switch_row_(stream, obj, area, node, friendly_name);
47#endif
48
49#ifdef USE_LOCK
50 this->lock_type_(stream);
51 for (auto *obj : App.get_locks())
52 this->lock_row_(stream, obj, area, node, friendly_name);
53#endif
54
55#ifdef USE_EVENT
56 this->event_type_(stream);
57 for (auto *obj : App.get_events())
58 this->event_row_(stream, obj, area, node, friendly_name);
59#endif
60
61#ifdef USE_TEXT
62 this->text_type_(stream);
63 for (auto *obj : App.get_texts())
64 this->text_row_(stream, obj, area, node, friendly_name);
65#endif
66
67#ifdef USE_TEXT_SENSOR
68 this->text_sensor_type_(stream);
69 for (auto *obj : App.get_text_sensors())
70 this->text_sensor_row_(stream, obj, area, node, friendly_name);
71#endif
72
73#ifdef USE_NUMBER
74 this->number_type_(stream);
75 for (auto *obj : App.get_numbers())
76 this->number_row_(stream, obj, area, node, friendly_name);
77#endif
78
79#ifdef USE_SELECT
80 this->select_type_(stream);
81 for (auto *obj : App.get_selects())
82 this->select_row_(stream, obj, area, node, friendly_name);
83#endif
84
85#ifdef USE_MEDIA_PLAYER
86 this->media_player_type_(stream);
87 for (auto *obj : App.get_media_players())
88 this->media_player_row_(stream, obj, area, node, friendly_name);
89#endif
90
91#ifdef USE_UPDATE
92 this->update_entity_type_(stream);
93 for (auto *obj : App.get_updates())
94 this->update_entity_row_(stream, obj, area, node, friendly_name);
95#endif
96
97#ifdef USE_VALVE
98 this->valve_type_(stream);
99 for (auto *obj : App.get_valves())
100 this->valve_row_(stream, obj, area, node, friendly_name);
101#endif
102
103#ifdef USE_CLIMATE
104 this->climate_type_(stream);
105 for (auto *obj : App.get_climates())
106 this->climate_row_(stream, obj, area, node, friendly_name);
107#endif
108
109 req->send(stream);
110}
111
112std::string PrometheusHandler::relabel_id_(EntityBase *obj) {
113 auto item = relabel_map_id_.find(obj);
114 if (item != relabel_map_id_.end()) {
115 return item->second;
116 }
117 char object_id_buf[OBJECT_ID_MAX_LEN];
118 return obj->get_object_id_to(object_id_buf).str();
119}
120
121std::string PrometheusHandler::relabel_name_(EntityBase *obj) {
122 auto item = relabel_map_name_.find(obj);
123 return item == relabel_map_name_.end() ? obj->get_name() : item->second;
124}
125
126void PrometheusHandler::add_area_label_(AsyncResponseStream *stream, std::string &area) {
127 if (!area.empty()) {
128 stream->print(ESPHOME_F("\",area=\""));
129 stream->print(area.c_str());
130 }
131}
132
133void PrometheusHandler::add_node_label_(AsyncResponseStream *stream, std::string &node) {
134 if (!node.empty()) {
135 stream->print(ESPHOME_F("\",node=\""));
136 stream->print(node.c_str());
137 }
138}
139
140void PrometheusHandler::add_friendly_name_label_(AsyncResponseStream *stream, std::string &friendly_name) {
141 if (!friendly_name.empty()) {
142 stream->print(ESPHOME_F("\",friendly_name=\""));
143 stream->print(friendly_name.c_str());
144 }
145}
146
147#ifdef USE_ESP8266
148void PrometheusHandler::print_metric_labels_(AsyncResponseStream *stream, const __FlashStringHelper *metric_name,
149 EntityBase *obj, std::string &area, std::string &node,
150 std::string &friendly_name) {
151#else
152void PrometheusHandler::print_metric_labels_(AsyncResponseStream *stream, const char *metric_name, EntityBase *obj,
153 std::string &area, std::string &node, std::string &friendly_name) {
154#endif
155 stream->print(metric_name);
156 stream->print(ESPHOME_F("{id=\""));
157 stream->print(relabel_id_(obj).c_str());
158 add_area_label_(stream, area);
159 add_node_label_(stream, node);
160 add_friendly_name_label_(stream, friendly_name);
161 stream->print(ESPHOME_F("\",name=\""));
162 stream->print(relabel_name_(obj).c_str());
163}
164
165// Type-specific implementation
166#ifdef USE_SENSOR
167void PrometheusHandler::sensor_type_(AsyncResponseStream *stream) {
168 stream->print(ESPHOME_F("#TYPE esphome_sensor_value gauge\n"));
169 stream->print(ESPHOME_F("#TYPE esphome_sensor_failed gauge\n"));
170}
171void PrometheusHandler::sensor_row_(AsyncResponseStream *stream, sensor::Sensor *obj, std::string &area,
172 std::string &node, std::string &friendly_name) {
173 if (obj->is_internal() && !this->include_internal_)
174 return;
175 if (!std::isnan(obj->state)) {
176 // We have a valid value, output this value
177 stream->print(ESPHOME_F("esphome_sensor_failed{id=\""));
178 stream->print(relabel_id_(obj).c_str());
179 add_area_label_(stream, area);
180 add_node_label_(stream, node);
181 add_friendly_name_label_(stream, friendly_name);
182 stream->print(ESPHOME_F("\",name=\""));
183 stream->print(relabel_name_(obj).c_str());
184 stream->print(ESPHOME_F("\"} 0\n"));
185 // Data itself
186 stream->print(ESPHOME_F("esphome_sensor_value{id=\""));
187 stream->print(relabel_id_(obj).c_str());
188 add_area_label_(stream, area);
189 add_node_label_(stream, node);
190 add_friendly_name_label_(stream, friendly_name);
191 stream->print(ESPHOME_F("\",name=\""));
192 stream->print(relabel_name_(obj).c_str());
193 stream->print(ESPHOME_F("\",unit=\""));
194 stream->print(obj->get_unit_of_measurement_ref().c_str());
195 stream->print(ESPHOME_F("\"} "));
196 char value_buf[VALUE_ACCURACY_MAX_LEN];
197 value_accuracy_to_buf(value_buf, obj->state, obj->get_accuracy_decimals());
198 stream->print(value_buf);
199 stream->print(ESPHOME_F("\n"));
200 } else {
201 // Invalid state
202 stream->print(ESPHOME_F("esphome_sensor_failed{id=\""));
203 stream->print(relabel_id_(obj).c_str());
204 add_area_label_(stream, area);
205 add_node_label_(stream, node);
206 add_friendly_name_label_(stream, friendly_name);
207 stream->print(ESPHOME_F("\",name=\""));
208 stream->print(relabel_name_(obj).c_str());
209 stream->print(ESPHOME_F("\"} 1\n"));
210 }
211}
212#endif
213
214// Type-specific implementation
215#ifdef USE_BINARY_SENSOR
216void PrometheusHandler::binary_sensor_type_(AsyncResponseStream *stream) {
217 stream->print(ESPHOME_F("#TYPE esphome_binary_sensor_value gauge\n"));
218 stream->print(ESPHOME_F("#TYPE esphome_binary_sensor_failed gauge\n"));
219}
220void PrometheusHandler::binary_sensor_row_(AsyncResponseStream *stream, binary_sensor::BinarySensor *obj,
221 std::string &area, std::string &node, std::string &friendly_name) {
222 if (obj->is_internal() && !this->include_internal_)
223 return;
224 if (obj->has_state()) {
225 // We have a valid value, output this value
226 stream->print(ESPHOME_F("esphome_binary_sensor_failed{id=\""));
227 stream->print(relabel_id_(obj).c_str());
228 add_area_label_(stream, area);
229 add_node_label_(stream, node);
230 add_friendly_name_label_(stream, friendly_name);
231 stream->print(ESPHOME_F("\",name=\""));
232 stream->print(relabel_name_(obj).c_str());
233 stream->print(ESPHOME_F("\"} 0\n"));
234 // Data itself
235 stream->print(ESPHOME_F("esphome_binary_sensor_value{id=\""));
236 stream->print(relabel_id_(obj).c_str());
237 add_area_label_(stream, area);
238 add_node_label_(stream, node);
239 add_friendly_name_label_(stream, friendly_name);
240 stream->print(ESPHOME_F("\",name=\""));
241 stream->print(relabel_name_(obj).c_str());
242 stream->print(ESPHOME_F("\"} "));
243 stream->print(obj->state);
244 stream->print(ESPHOME_F("\n"));
245 } else {
246 // Invalid state
247 stream->print(ESPHOME_F("esphome_binary_sensor_failed{id=\""));
248 stream->print(relabel_id_(obj).c_str());
249 add_area_label_(stream, area);
250 add_node_label_(stream, node);
251 add_friendly_name_label_(stream, friendly_name);
252 stream->print(ESPHOME_F("\",name=\""));
253 stream->print(relabel_name_(obj).c_str());
254 stream->print(ESPHOME_F("\"} 1\n"));
255 }
256}
257#endif
258
259#ifdef USE_FAN
260void PrometheusHandler::fan_type_(AsyncResponseStream *stream) {
261 stream->print(ESPHOME_F("#TYPE esphome_fan_value gauge\n"));
262 stream->print(ESPHOME_F("#TYPE esphome_fan_failed gauge\n"));
263 stream->print(ESPHOME_F("#TYPE esphome_fan_speed gauge\n"));
264 stream->print(ESPHOME_F("#TYPE esphome_fan_oscillation gauge\n"));
265}
266void PrometheusHandler::fan_row_(AsyncResponseStream *stream, fan::Fan *obj, std::string &area, std::string &node,
267 std::string &friendly_name) {
268 if (obj->is_internal() && !this->include_internal_)
269 return;
270 stream->print(ESPHOME_F("esphome_fan_failed{id=\""));
271 stream->print(relabel_id_(obj).c_str());
272 add_area_label_(stream, area);
273 add_node_label_(stream, node);
274 add_friendly_name_label_(stream, friendly_name);
275 stream->print(ESPHOME_F("\",name=\""));
276 stream->print(relabel_name_(obj).c_str());
277 stream->print(ESPHOME_F("\"} 0\n"));
278 // Data itself
279 stream->print(ESPHOME_F("esphome_fan_value{id=\""));
280 stream->print(relabel_id_(obj).c_str());
281 add_area_label_(stream, area);
282 add_node_label_(stream, node);
283 add_friendly_name_label_(stream, friendly_name);
284 stream->print(ESPHOME_F("\",name=\""));
285 stream->print(relabel_name_(obj).c_str());
286 stream->print(ESPHOME_F("\"} "));
287 stream->print(obj->state);
288 stream->print(ESPHOME_F("\n"));
289 // Speed if available
290 if (obj->get_traits().supports_speed()) {
291 stream->print(ESPHOME_F("esphome_fan_speed{id=\""));
292 stream->print(relabel_id_(obj).c_str());
293 add_area_label_(stream, area);
294 add_node_label_(stream, node);
295 add_friendly_name_label_(stream, friendly_name);
296 stream->print(ESPHOME_F("\",name=\""));
297 stream->print(relabel_name_(obj).c_str());
298 stream->print(ESPHOME_F("\"} "));
299 stream->print(obj->speed);
300 stream->print(ESPHOME_F("\n"));
301 }
302 // Oscillation if available
303 if (obj->get_traits().supports_oscillation()) {
304 stream->print(ESPHOME_F("esphome_fan_oscillation{id=\""));
305 stream->print(relabel_id_(obj).c_str());
306 add_area_label_(stream, area);
307 add_node_label_(stream, node);
308 add_friendly_name_label_(stream, friendly_name);
309 stream->print(ESPHOME_F("\",name=\""));
310 stream->print(relabel_name_(obj).c_str());
311 stream->print(ESPHOME_F("\"} "));
312 stream->print(obj->oscillating);
313 stream->print(ESPHOME_F("\n"));
314 }
315}
316#endif
317
318#ifdef USE_LIGHT
319void PrometheusHandler::light_type_(AsyncResponseStream *stream) {
320 stream->print(ESPHOME_F("#TYPE esphome_light_state gauge\n"));
321 stream->print(ESPHOME_F("#TYPE esphome_light_color gauge\n"));
322 stream->print(ESPHOME_F("#TYPE esphome_light_effect_active gauge\n"));
323}
324void PrometheusHandler::light_row_(AsyncResponseStream *stream, light::LightState *obj, std::string &area,
325 std::string &node, std::string &friendly_name) {
326 if (obj->is_internal() && !this->include_internal_)
327 return;
328 // State
329 print_metric_labels_(stream, ESPHOME_F("esphome_light_state"), obj, area, node, friendly_name);
330 stream->print(ESPHOME_F("\"} "));
331 stream->print(obj->remote_values.is_on());
332 stream->print(ESPHOME_F("\n"));
333 // Brightness and RGBW
334 light::LightColorValues color = obj->current_values;
335 float brightness, r, g, b, w;
336 color.as_brightness(&brightness);
337 color.as_rgbw(&r, &g, &b, &w);
338 if (obj->get_traits().supports_color_capability(light::ColorCapability::BRIGHTNESS)) {
339 print_metric_labels_(stream, ESPHOME_F("esphome_light_color"), obj, area, node, friendly_name);
340 stream->print(ESPHOME_F("\",channel=\"brightness\"} "));
341 stream->print(brightness);
342 stream->print(ESPHOME_F("\n"));
343 }
344 if (obj->get_traits().supports_color_capability(light::ColorCapability::RGB)) {
345 print_metric_labels_(stream, ESPHOME_F("esphome_light_color"), obj, area, node, friendly_name);
346 stream->print(ESPHOME_F("\",channel=\"r\"} "));
347 stream->print(r);
348 stream->print(ESPHOME_F("\n"));
349 print_metric_labels_(stream, ESPHOME_F("esphome_light_color"), obj, area, node, friendly_name);
350 stream->print(ESPHOME_F("\",channel=\"g\"} "));
351 stream->print(g);
352 stream->print(ESPHOME_F("\n"));
353 print_metric_labels_(stream, ESPHOME_F("esphome_light_color"), obj, area, node, friendly_name);
354 stream->print(ESPHOME_F("\",channel=\"b\"} "));
355 stream->print(b);
356 stream->print(ESPHOME_F("\n"));
357 }
358 if (obj->get_traits().supports_color_capability(light::ColorCapability::WHITE)) {
359 print_metric_labels_(stream, ESPHOME_F("esphome_light_color"), obj, area, node, friendly_name);
360 stream->print(ESPHOME_F("\",channel=\"w\"} "));
361 stream->print(w);
362 stream->print(ESPHOME_F("\n"));
363 }
364 // Skip effect metrics if light has no effects
365 if (!obj->get_effects().empty()) {
366 // Effect
367 StringRef effect = obj->get_effect_name();
368 print_metric_labels_(stream, ESPHOME_F("esphome_light_effect_active"), obj, area, node, friendly_name);
369 stream->print(ESPHOME_F("\",effect=\""));
370 // Only vary based on effect
371 if (effect == "None") {
372 stream->print(ESPHOME_F("None\"} 0\n"));
373 } else {
374 // c_str() is safe as effect names are null-terminated strings from codegen
375 stream->print(effect.c_str());
376 stream->print(ESPHOME_F("\"} 1\n"));
377 }
378 }
379}
380#endif
381
382#ifdef USE_COVER
383void PrometheusHandler::cover_type_(AsyncResponseStream *stream) {
384 stream->print(ESPHOME_F("#TYPE esphome_cover_value gauge\n"));
385 stream->print(ESPHOME_F("#TYPE esphome_cover_failed gauge\n"));
386}
387void PrometheusHandler::cover_row_(AsyncResponseStream *stream, cover::Cover *obj, std::string &area, std::string &node,
388 std::string &friendly_name) {
389 if (obj->is_internal() && !this->include_internal_)
390 return;
391 if (!std::isnan(obj->position)) {
392 // We have a valid value, output this value
393 stream->print(ESPHOME_F("esphome_cover_failed{id=\""));
394 stream->print(relabel_id_(obj).c_str());
395 add_area_label_(stream, area);
396 add_node_label_(stream, node);
397 add_friendly_name_label_(stream, friendly_name);
398 stream->print(ESPHOME_F("\",name=\""));
399 stream->print(relabel_name_(obj).c_str());
400 stream->print(ESPHOME_F("\"} 0\n"));
401 // Data itself
402 stream->print(ESPHOME_F("esphome_cover_value{id=\""));
403 stream->print(relabel_id_(obj).c_str());
404 add_area_label_(stream, area);
405 add_node_label_(stream, node);
406 add_friendly_name_label_(stream, friendly_name);
407 stream->print(ESPHOME_F("\",name=\""));
408 stream->print(relabel_name_(obj).c_str());
409 stream->print(ESPHOME_F("\"} "));
410 stream->print(obj->position);
411 stream->print(ESPHOME_F("\n"));
412 if (obj->get_traits().get_supports_tilt()) {
413 stream->print(ESPHOME_F("esphome_cover_tilt{id=\""));
414 stream->print(relabel_id_(obj).c_str());
415 add_area_label_(stream, area);
416 add_node_label_(stream, node);
417 add_friendly_name_label_(stream, friendly_name);
418 stream->print(ESPHOME_F("\",name=\""));
419 stream->print(relabel_name_(obj).c_str());
420 stream->print(ESPHOME_F("\"} "));
421 stream->print(obj->tilt);
422 stream->print(ESPHOME_F("\n"));
423 }
424 } else {
425 // Invalid state
426 stream->print(ESPHOME_F("esphome_cover_failed{id=\""));
427 stream->print(relabel_id_(obj).c_str());
428 add_area_label_(stream, area);
429 add_node_label_(stream, node);
430 add_friendly_name_label_(stream, friendly_name);
431 stream->print(ESPHOME_F("\",name=\""));
432 stream->print(relabel_name_(obj).c_str());
433 stream->print(ESPHOME_F("\"} 1\n"));
434 }
435}
436#endif
437
438#ifdef USE_SWITCH
439void PrometheusHandler::switch_type_(AsyncResponseStream *stream) {
440 stream->print(ESPHOME_F("#TYPE esphome_switch_value gauge\n"));
441 stream->print(ESPHOME_F("#TYPE esphome_switch_failed gauge\n"));
442}
443void PrometheusHandler::switch_row_(AsyncResponseStream *stream, switch_::Switch *obj, std::string &area,
444 std::string &node, std::string &friendly_name) {
445 if (obj->is_internal() && !this->include_internal_)
446 return;
447 stream->print(ESPHOME_F("esphome_switch_failed{id=\""));
448 stream->print(relabel_id_(obj).c_str());
449 add_area_label_(stream, area);
450 add_node_label_(stream, node);
451 add_friendly_name_label_(stream, friendly_name);
452 stream->print(ESPHOME_F("\",name=\""));
453 stream->print(relabel_name_(obj).c_str());
454 stream->print(ESPHOME_F("\"} 0\n"));
455 // Data itself
456 stream->print(ESPHOME_F("esphome_switch_value{id=\""));
457 stream->print(relabel_id_(obj).c_str());
458 add_area_label_(stream, area);
459 add_node_label_(stream, node);
460 add_friendly_name_label_(stream, friendly_name);
461 stream->print(ESPHOME_F("\",name=\""));
462 stream->print(relabel_name_(obj).c_str());
463 stream->print(ESPHOME_F("\"} "));
464 stream->print(obj->state);
465 stream->print(ESPHOME_F("\n"));
466}
467#endif
468
469#ifdef USE_LOCK
470void PrometheusHandler::lock_type_(AsyncResponseStream *stream) {
471 stream->print(ESPHOME_F("#TYPE esphome_lock_value gauge\n"));
472 stream->print(ESPHOME_F("#TYPE esphome_lock_failed gauge\n"));
473}
474void PrometheusHandler::lock_row_(AsyncResponseStream *stream, lock::Lock *obj, std::string &area, std::string &node,
475 std::string &friendly_name) {
476 if (obj->is_internal() && !this->include_internal_)
477 return;
478 stream->print(ESPHOME_F("esphome_lock_failed{id=\""));
479 stream->print(relabel_id_(obj).c_str());
480 add_area_label_(stream, area);
481 add_node_label_(stream, node);
482 add_friendly_name_label_(stream, friendly_name);
483 stream->print(ESPHOME_F("\",name=\""));
484 stream->print(relabel_name_(obj).c_str());
485 stream->print(ESPHOME_F("\"} 0\n"));
486 // Data itself
487 stream->print(ESPHOME_F("esphome_lock_value{id=\""));
488 stream->print(relabel_id_(obj).c_str());
489 add_area_label_(stream, area);
490 add_node_label_(stream, node);
491 add_friendly_name_label_(stream, friendly_name);
492 stream->print(ESPHOME_F("\",name=\""));
493 stream->print(relabel_name_(obj).c_str());
494 stream->print(ESPHOME_F("\"} "));
495 stream->print(obj->state);
496 stream->print(ESPHOME_F("\n"));
497}
498#endif
499
500// Type-specific implementation
501#ifdef USE_TEXT_SENSOR
502void PrometheusHandler::text_sensor_type_(AsyncResponseStream *stream) {
503 stream->print(ESPHOME_F("#TYPE esphome_text_sensor_value gauge\n"));
504 stream->print(ESPHOME_F("#TYPE esphome_text_sensor_failed gauge\n"));
505}
506void PrometheusHandler::text_sensor_row_(AsyncResponseStream *stream, text_sensor::TextSensor *obj, std::string &area,
507 std::string &node, std::string &friendly_name) {
508 if (obj->is_internal() && !this->include_internal_)
509 return;
510 if (obj->has_state()) {
511 // We have a valid value, output this value
512 stream->print(ESPHOME_F("esphome_text_sensor_failed{id=\""));
513 stream->print(relabel_id_(obj).c_str());
514 add_area_label_(stream, area);
515 add_node_label_(stream, node);
516 add_friendly_name_label_(stream, friendly_name);
517 stream->print(ESPHOME_F("\",name=\""));
518 stream->print(relabel_name_(obj).c_str());
519 stream->print(ESPHOME_F("\"} 0\n"));
520 // Data itself
521 stream->print(ESPHOME_F("esphome_text_sensor_value{id=\""));
522 stream->print(relabel_id_(obj).c_str());
523 add_area_label_(stream, area);
524 add_node_label_(stream, node);
525 add_friendly_name_label_(stream, friendly_name);
526 stream->print(ESPHOME_F("\",name=\""));
527 stream->print(relabel_name_(obj).c_str());
528 stream->print(ESPHOME_F("\",value=\""));
529 stream->print(obj->state.c_str());
530 stream->print(ESPHOME_F("\"} "));
531 stream->print(ESPHOME_F("1.0"));
532 stream->print(ESPHOME_F("\n"));
533 } else {
534 // Invalid state
535 stream->print(ESPHOME_F("esphome_text_sensor_failed{id=\""));
536 stream->print(relabel_id_(obj).c_str());
537 add_area_label_(stream, area);
538 add_node_label_(stream, node);
539 add_friendly_name_label_(stream, friendly_name);
540 stream->print(ESPHOME_F("\",name=\""));
541 stream->print(relabel_name_(obj).c_str());
542 stream->print(ESPHOME_F("\"} 1\n"));
543 }
544}
545#endif
546
547// Type-specific implementation
548#ifdef USE_TEXT
549void PrometheusHandler::text_type_(AsyncResponseStream *stream) {
550 stream->print(ESPHOME_F("#TYPE esphome_text_value gauge\n"));
551 stream->print(ESPHOME_F("#TYPE esphome_text_failed gauge\n"));
552}
553void PrometheusHandler::text_row_(AsyncResponseStream *stream, text::Text *obj, std::string &area, std::string &node,
554 std::string &friendly_name) {
555 if (obj->is_internal() && !this->include_internal_)
556 return;
557 if (obj->has_state()) {
558 // We have a valid value, output this value
559 stream->print(ESPHOME_F("esphome_text_failed{id=\""));
560 stream->print(relabel_id_(obj).c_str());
561 add_area_label_(stream, area);
562 add_node_label_(stream, node);
563 add_friendly_name_label_(stream, friendly_name);
564 stream->print(ESPHOME_F("\",name=\""));
565 stream->print(relabel_name_(obj).c_str());
566 stream->print(ESPHOME_F("\"} 0\n"));
567 // Data itself
568 stream->print(ESPHOME_F("esphome_text_value{id=\""));
569 stream->print(relabel_id_(obj).c_str());
570 add_area_label_(stream, area);
571 add_node_label_(stream, node);
572 add_friendly_name_label_(stream, friendly_name);
573 stream->print(ESPHOME_F("\",name=\""));
574 stream->print(relabel_name_(obj).c_str());
575 stream->print(ESPHOME_F("\",value=\""));
576 stream->print(obj->state.c_str());
577 stream->print(ESPHOME_F("\"} "));
578 stream->print(ESPHOME_F("1.0"));
579 stream->print(ESPHOME_F("\n"));
580 } else {
581 // Invalid state
582 stream->print(ESPHOME_F("esphome_text_failed{id=\""));
583 stream->print(relabel_id_(obj).c_str());
584 add_area_label_(stream, area);
585 add_node_label_(stream, node);
586 add_friendly_name_label_(stream, friendly_name);
587 stream->print(ESPHOME_F("\",name=\""));
588 stream->print(relabel_name_(obj).c_str());
589 stream->print(ESPHOME_F("\"} 1\n"));
590 }
591}
592#endif
593
594// Type-specific implementation
595#ifdef USE_EVENT
596void PrometheusHandler::event_type_(AsyncResponseStream *stream) {
597 stream->print(ESPHOME_F("#TYPE esphome_event_value gauge\n"));
598 stream->print(ESPHOME_F("#TYPE esphome_event_failed gauge\n"));
599}
600void PrometheusHandler::event_row_(AsyncResponseStream *stream, event::Event *obj, std::string &area, std::string &node,
601 std::string &friendly_name) {
602 if (obj->is_internal() && !this->include_internal_)
603 return;
604 if (obj->has_event()) {
605 // We have a valid event type, output this value
606 stream->print(ESPHOME_F("esphome_event_failed{id=\""));
607 stream->print(relabel_id_(obj).c_str());
608 add_area_label_(stream, area);
609 add_node_label_(stream, node);
610 add_friendly_name_label_(stream, friendly_name);
611 stream->print(ESPHOME_F("\",name=\""));
612 stream->print(relabel_name_(obj).c_str());
613 stream->print(ESPHOME_F("\"} 0\n"));
614 // Data itself
615 stream->print(ESPHOME_F("esphome_event_value{id=\""));
616 stream->print(relabel_id_(obj).c_str());
617 add_area_label_(stream, area);
618 add_node_label_(stream, node);
619 add_friendly_name_label_(stream, friendly_name);
620 stream->print(ESPHOME_F("\",name=\""));
621 stream->print(relabel_name_(obj).c_str());
622 stream->print(ESPHOME_F("\",last_event_type=\""));
623 // get_last_event_type() returns StringRef (null-terminated)
624 stream->print(obj->get_last_event_type().c_str());
625 stream->print(ESPHOME_F("\"} "));
626 stream->print(ESPHOME_F("1.0"));
627 stream->print(ESPHOME_F("\n"));
628 } else {
629 // No event triggered yet
630 stream->print(ESPHOME_F("esphome_event_failed{id=\""));
631 stream->print(relabel_id_(obj).c_str());
632 add_area_label_(stream, area);
633 add_node_label_(stream, node);
634 add_friendly_name_label_(stream, friendly_name);
635 stream->print(ESPHOME_F("\",name=\""));
636 stream->print(relabel_name_(obj).c_str());
637 stream->print(ESPHOME_F("\"} 1\n"));
638 }
639}
640#endif
641
642// Type-specific implementation
643#ifdef USE_NUMBER
644void PrometheusHandler::number_type_(AsyncResponseStream *stream) {
645 stream->print(ESPHOME_F("#TYPE esphome_number_value gauge\n"));
646 stream->print(ESPHOME_F("#TYPE esphome_number_failed gauge\n"));
647}
648void PrometheusHandler::number_row_(AsyncResponseStream *stream, number::Number *obj, std::string &area,
649 std::string &node, std::string &friendly_name) {
650 if (obj->is_internal() && !this->include_internal_)
651 return;
652 if (!std::isnan(obj->state)) {
653 // We have a valid value, output this value
654 stream->print(ESPHOME_F("esphome_number_failed{id=\""));
655 stream->print(relabel_id_(obj).c_str());
656 add_area_label_(stream, area);
657 add_node_label_(stream, node);
658 add_friendly_name_label_(stream, friendly_name);
659 stream->print(ESPHOME_F("\",name=\""));
660 stream->print(relabel_name_(obj).c_str());
661 stream->print(ESPHOME_F("\"} 0\n"));
662 // Data itself
663 stream->print(ESPHOME_F("esphome_number_value{id=\""));
664 stream->print(relabel_id_(obj).c_str());
665 add_area_label_(stream, area);
666 add_node_label_(stream, node);
667 add_friendly_name_label_(stream, friendly_name);
668 stream->print(ESPHOME_F("\",name=\""));
669 stream->print(relabel_name_(obj).c_str());
670 stream->print(ESPHOME_F("\"} "));
671 stream->print(obj->state);
672 stream->print(ESPHOME_F("\n"));
673 } else {
674 // Invalid state
675 stream->print(ESPHOME_F("esphome_number_failed{id=\""));
676 stream->print(relabel_id_(obj).c_str());
677 add_area_label_(stream, area);
678 add_node_label_(stream, node);
679 add_friendly_name_label_(stream, friendly_name);
680 stream->print(ESPHOME_F("\",name=\""));
681 stream->print(relabel_name_(obj).c_str());
682 stream->print(ESPHOME_F("\"} 1\n"));
683 }
684}
685#endif
686
687#ifdef USE_SELECT
688void PrometheusHandler::select_type_(AsyncResponseStream *stream) {
689 stream->print(ESPHOME_F("#TYPE esphome_select_value gauge\n"));
690 stream->print(ESPHOME_F("#TYPE esphome_select_failed gauge\n"));
691}
692void PrometheusHandler::select_row_(AsyncResponseStream *stream, select::Select *obj, std::string &area,
693 std::string &node, std::string &friendly_name) {
694 if (obj->is_internal() && !this->include_internal_)
695 return;
696 if (obj->has_state()) {
697 // We have a valid value, output this value
698 stream->print(ESPHOME_F("esphome_select_failed{id=\""));
699 stream->print(relabel_id_(obj).c_str());
700 add_area_label_(stream, area);
701 add_node_label_(stream, node);
702 add_friendly_name_label_(stream, friendly_name);
703 stream->print(ESPHOME_F("\",name=\""));
704 stream->print(relabel_name_(obj).c_str());
705 stream->print(ESPHOME_F("\"} 0\n"));
706 // Data itself
707 stream->print(ESPHOME_F("esphome_select_value{id=\""));
708 stream->print(relabel_id_(obj).c_str());
709 add_area_label_(stream, area);
710 add_node_label_(stream, node);
711 add_friendly_name_label_(stream, friendly_name);
712 stream->print(ESPHOME_F("\",name=\""));
713 stream->print(relabel_name_(obj).c_str());
714 stream->print(ESPHOME_F("\",value=\""));
715 // c_str() is safe as option values are null-terminated strings from codegen
716 stream->print(obj->current_option().c_str());
717 stream->print(ESPHOME_F("\"} "));
718 stream->print(ESPHOME_F("1.0"));
719 stream->print(ESPHOME_F("\n"));
720 } else {
721 // Invalid state
722 stream->print(ESPHOME_F("esphome_select_failed{id=\""));
723 stream->print(relabel_id_(obj).c_str());
724 add_area_label_(stream, area);
725 add_node_label_(stream, node);
726 add_friendly_name_label_(stream, friendly_name);
727 stream->print(ESPHOME_F("\",name=\""));
728 stream->print(relabel_name_(obj).c_str());
729 stream->print(ESPHOME_F("\"} 1\n"));
730 }
731}
732#endif
733
734#ifdef USE_MEDIA_PLAYER
735void PrometheusHandler::media_player_type_(AsyncResponseStream *stream) {
736 stream->print(ESPHOME_F("#TYPE esphome_media_player_state_value gauge\n"));
737 stream->print(ESPHOME_F("#TYPE esphome_media_player_volume gauge\n"));
738 stream->print(ESPHOME_F("#TYPE esphome_media_player_is_muted gauge\n"));
739 stream->print(ESPHOME_F("#TYPE esphome_media_player_failed gauge\n"));
740}
741void PrometheusHandler::media_player_row_(AsyncResponseStream *stream, media_player::MediaPlayer *obj,
742 std::string &area, std::string &node, std::string &friendly_name) {
743 if (obj->is_internal() && !this->include_internal_)
744 return;
745 stream->print(ESPHOME_F("esphome_media_player_failed{id=\""));
746 stream->print(relabel_id_(obj).c_str());
747 add_area_label_(stream, area);
748 add_node_label_(stream, node);
749 add_friendly_name_label_(stream, friendly_name);
750 stream->print(ESPHOME_F("\",name=\""));
751 stream->print(relabel_name_(obj).c_str());
752 stream->print(ESPHOME_F("\"} 0\n"));
753 // Data itself
754 stream->print(ESPHOME_F("esphome_media_player_state_value{id=\""));
755 stream->print(relabel_id_(obj).c_str());
756 add_area_label_(stream, area);
757 add_node_label_(stream, node);
758 add_friendly_name_label_(stream, friendly_name);
759 stream->print(ESPHOME_F("\",name=\""));
760 stream->print(relabel_name_(obj).c_str());
761 stream->print(ESPHOME_F("\",value=\""));
762 stream->print(media_player::media_player_state_to_string(obj->state));
763 stream->print(ESPHOME_F("\"} "));
764 stream->print(ESPHOME_F("1.0"));
765 stream->print(ESPHOME_F("\n"));
766 stream->print(ESPHOME_F("esphome_media_player_volume{id=\""));
767 stream->print(relabel_id_(obj).c_str());
768 add_area_label_(stream, area);
769 add_node_label_(stream, node);
770 add_friendly_name_label_(stream, friendly_name);
771 stream->print(ESPHOME_F("\",name=\""));
772 stream->print(relabel_name_(obj).c_str());
773 stream->print(ESPHOME_F("\"} "));
774 stream->print(obj->volume);
775 stream->print(ESPHOME_F("\n"));
776 stream->print(ESPHOME_F("esphome_media_player_is_muted{id=\""));
777 stream->print(relabel_id_(obj).c_str());
778 add_area_label_(stream, area);
779 add_node_label_(stream, node);
780 add_friendly_name_label_(stream, friendly_name);
781 stream->print(ESPHOME_F("\",name=\""));
782 stream->print(relabel_name_(obj).c_str());
783 stream->print(ESPHOME_F("\"} "));
784 if (obj->is_muted()) {
785 stream->print(ESPHOME_F("1.0"));
786 } else {
787 stream->print(ESPHOME_F("0.0"));
788 }
789 stream->print(ESPHOME_F("\n"));
790}
791#endif
792
793#ifdef USE_UPDATE
794void PrometheusHandler::update_entity_type_(AsyncResponseStream *stream) {
795 stream->print(ESPHOME_F("#TYPE esphome_update_entity_state gauge\n"));
796 stream->print(ESPHOME_F("#TYPE esphome_update_entity_info gauge\n"));
797 stream->print(ESPHOME_F("#TYPE esphome_update_entity_failed gauge\n"));
798}
799
800void PrometheusHandler::handle_update_state_(AsyncResponseStream *stream, update::UpdateState state) {
801 switch (state) {
803 stream->print("unknown");
804 break;
806 stream->print("none");
807 break;
809 stream->print("available");
810 break;
812 stream->print("installing");
813 break;
814 default:
815 stream->print("invalid");
816 break;
817 }
818}
819
820void PrometheusHandler::update_entity_row_(AsyncResponseStream *stream, update::UpdateEntity *obj, std::string &area,
821 std::string &node, std::string &friendly_name) {
822 if (obj->is_internal() && !this->include_internal_)
823 return;
824 if (obj->has_state()) {
825 // We have a valid value, output this value
826 stream->print(ESPHOME_F("esphome_update_entity_failed{id=\""));
827 stream->print(relabel_id_(obj).c_str());
828 add_area_label_(stream, area);
829 add_node_label_(stream, node);
830 add_friendly_name_label_(stream, friendly_name);
831 stream->print(ESPHOME_F("\",name=\""));
832 stream->print(relabel_name_(obj).c_str());
833 stream->print(ESPHOME_F("\"} 0\n"));
834 // First update state
835 stream->print(ESPHOME_F("esphome_update_entity_state{id=\""));
836 stream->print(relabel_id_(obj).c_str());
837 add_area_label_(stream, area);
838 add_node_label_(stream, node);
839 add_friendly_name_label_(stream, friendly_name);
840 stream->print(ESPHOME_F("\",name=\""));
841 stream->print(relabel_name_(obj).c_str());
842 stream->print(ESPHOME_F("\",value=\""));
843 handle_update_state_(stream, obj->state);
844 stream->print(ESPHOME_F("\"} "));
845 stream->print(ESPHOME_F("1.0"));
846 stream->print(ESPHOME_F("\n"));
847 // Next update info
848 stream->print(ESPHOME_F("esphome_update_entity_info{id=\""));
849 stream->print(relabel_id_(obj).c_str());
850 add_area_label_(stream, area);
851 add_node_label_(stream, node);
852 add_friendly_name_label_(stream, friendly_name);
853 stream->print(ESPHOME_F("\",name=\""));
854 stream->print(relabel_name_(obj).c_str());
855 stream->print(ESPHOME_F("\",current_version=\""));
856 stream->print(obj->update_info.current_version.c_str());
857 stream->print(ESPHOME_F("\",latest_version=\""));
858 stream->print(obj->update_info.latest_version.c_str());
859 stream->print(ESPHOME_F("\",title=\""));
860 stream->print(obj->update_info.title.c_str());
861 stream->print(ESPHOME_F("\"} "));
862 stream->print(ESPHOME_F("1.0"));
863 stream->print(ESPHOME_F("\n"));
864 } else {
865 // Invalid state
866 stream->print(ESPHOME_F("esphome_update_entity_failed{id=\""));
867 stream->print(relabel_id_(obj).c_str());
868 add_area_label_(stream, area);
869 add_node_label_(stream, node);
870 add_friendly_name_label_(stream, friendly_name);
871 stream->print(ESPHOME_F("\",name=\""));
872 stream->print(relabel_name_(obj).c_str());
873 stream->print(ESPHOME_F("\"} 1\n"));
874 }
875}
876#endif
877
878#ifdef USE_VALVE
879void PrometheusHandler::valve_type_(AsyncResponseStream *stream) {
880 stream->print(ESPHOME_F("#TYPE esphome_valve_operation gauge\n"));
881 stream->print(ESPHOME_F("#TYPE esphome_valve_failed gauge\n"));
882 stream->print(ESPHOME_F("#TYPE esphome_valve_position gauge\n"));
883}
884
885void PrometheusHandler::valve_row_(AsyncResponseStream *stream, valve::Valve *obj, std::string &area, std::string &node,
886 std::string &friendly_name) {
887 if (obj->is_internal() && !this->include_internal_)
888 return;
889 stream->print(ESPHOME_F("esphome_valve_failed{id=\""));
890 stream->print(relabel_id_(obj).c_str());
891 add_area_label_(stream, area);
892 add_node_label_(stream, node);
893 add_friendly_name_label_(stream, friendly_name);
894 stream->print(ESPHOME_F("\",name=\""));
895 stream->print(relabel_name_(obj).c_str());
896 stream->print(ESPHOME_F("\"} 0\n"));
897 // Data itself
898 stream->print(ESPHOME_F("esphome_valve_operation{id=\""));
899 stream->print(relabel_id_(obj).c_str());
900 add_area_label_(stream, area);
901 add_node_label_(stream, node);
902 add_friendly_name_label_(stream, friendly_name);
903 stream->print(ESPHOME_F("\",name=\""));
904 stream->print(relabel_name_(obj).c_str());
905 stream->print(ESPHOME_F("\",operation=\""));
906#ifdef USE_STORE_LOG_STR_IN_FLASH
907 stream->print((const __FlashStringHelper *) valve::valve_operation_to_str(obj->current_operation));
908#else
909 stream->print((const char *) valve::valve_operation_to_str(obj->current_operation));
910#endif
911 stream->print(ESPHOME_F("\"} "));
912 stream->print(ESPHOME_F("1.0"));
913 stream->print(ESPHOME_F("\n"));
914 // Now see if position is supported
915 if (obj->get_traits().get_supports_position()) {
916 stream->print(ESPHOME_F("esphome_valve_position{id=\""));
917 stream->print(relabel_id_(obj).c_str());
918 add_area_label_(stream, area);
919 add_node_label_(stream, node);
920 add_friendly_name_label_(stream, friendly_name);
921 stream->print(ESPHOME_F("\",name=\""));
922 stream->print(relabel_name_(obj).c_str());
923 stream->print(ESPHOME_F("\"} "));
924 stream->print(obj->position);
925 stream->print(ESPHOME_F("\n"));
926 }
927}
928#endif
929
930#ifdef USE_CLIMATE
931void PrometheusHandler::climate_type_(AsyncResponseStream *stream) {
932 stream->print(ESPHOME_F("#TYPE esphome_climate_setting gauge\n"));
933 stream->print(ESPHOME_F("#TYPE esphome_climate_value gauge\n"));
934 stream->print(ESPHOME_F("#TYPE esphome_climate_failed gauge\n"));
935}
936
937void PrometheusHandler::climate_setting_row_(AsyncResponseStream *stream, climate::Climate *obj, std::string &area,
938 std::string &node, std::string &friendly_name, std::string &setting,
939 const LogString *setting_value) {
940 stream->print(ESPHOME_F("esphome_climate_setting{id=\""));
941 stream->print(relabel_id_(obj).c_str());
942 add_area_label_(stream, area);
943 add_node_label_(stream, node);
944 add_friendly_name_label_(stream, friendly_name);
945 stream->print(ESPHOME_F("\",name=\""));
946 stream->print(relabel_name_(obj).c_str());
947 stream->print(ESPHOME_F("\",category=\""));
948 stream->print(setting.c_str());
949 stream->print(ESPHOME_F("\",setting_value=\""));
950 stream->print(LOG_STR_ARG(setting_value));
951 stream->print(ESPHOME_F("\"} "));
952 stream->print(ESPHOME_F("1.0"));
953 stream->print(ESPHOME_F("\n"));
954}
955
956void PrometheusHandler::climate_value_row_(AsyncResponseStream *stream, climate::Climate *obj, std::string &area,
957 std::string &node, std::string &friendly_name, std::string &category,
958 const char *climate_value) {
959 stream->print(ESPHOME_F("esphome_climate_value{id=\""));
960 stream->print(relabel_id_(obj).c_str());
961 add_area_label_(stream, area);
962 add_node_label_(stream, node);
963 add_friendly_name_label_(stream, friendly_name);
964 stream->print(ESPHOME_F("\",name=\""));
965 stream->print(relabel_name_(obj).c_str());
966 stream->print(ESPHOME_F("\",category=\""));
967 stream->print(category.c_str());
968 stream->print(ESPHOME_F("\"} "));
969 stream->print(climate_value);
970 stream->print(ESPHOME_F("\n"));
971}
972
973void PrometheusHandler::climate_failed_row_(AsyncResponseStream *stream, climate::Climate *obj, std::string &area,
974 std::string &node, std::string &friendly_name, std::string &category,
975 bool is_failed_value) {
976 stream->print(ESPHOME_F("esphome_climate_failed{id=\""));
977 stream->print(relabel_id_(obj).c_str());
978 add_area_label_(stream, area);
979 add_node_label_(stream, node);
980 add_friendly_name_label_(stream, friendly_name);
981 stream->print(ESPHOME_F("\",name=\""));
982 stream->print(relabel_name_(obj).c_str());
983 stream->print(ESPHOME_F("\",category=\""));
984 stream->print(category.c_str());
985 stream->print(ESPHOME_F("\"} "));
986 if (is_failed_value) {
987 stream->print(ESPHOME_F("1.0"));
988 } else {
989 stream->print(ESPHOME_F("0.0"));
990 }
991 stream->print(ESPHOME_F("\n"));
992}
993
994void PrometheusHandler::climate_row_(AsyncResponseStream *stream, climate::Climate *obj, std::string &area,
995 std::string &node, std::string &friendly_name) {
996 if (obj->is_internal() && !this->include_internal_)
997 return;
998 // Data itself
999 bool any_failures = false;
1000 std::string climate_mode_category = "mode";
1001 const auto *climate_mode_value = climate::climate_mode_to_string(obj->mode);
1002 climate_setting_row_(stream, obj, area, node, friendly_name, climate_mode_category, climate_mode_value);
1003 const auto traits = obj->get_traits();
1004 // Now see if traits is supported
1005 int8_t target_accuracy = traits.get_target_temperature_accuracy_decimals();
1006 int8_t current_accuracy = traits.get_current_temperature_accuracy_decimals();
1007 char value_buf[VALUE_ACCURACY_MAX_LEN];
1008 // max temp
1009 std::string max_temp = "maximum_temperature";
1010 value_accuracy_to_buf(value_buf, traits.get_visual_max_temperature(), target_accuracy);
1011 climate_value_row_(stream, obj, area, node, friendly_name, max_temp, value_buf);
1012 // min temp
1013 std::string min_temp = "minimum_temperature";
1014 value_accuracy_to_buf(value_buf, traits.get_visual_min_temperature(), target_accuracy);
1015 climate_value_row_(stream, obj, area, node, friendly_name, min_temp, value_buf);
1016 // now check optional traits
1017 if (traits.has_feature_flags(climate::CLIMATE_SUPPORTS_CURRENT_TEMPERATURE)) {
1018 std::string current_temp = "current_temperature";
1019 if (std::isnan(obj->current_temperature)) {
1020 climate_failed_row_(stream, obj, area, node, friendly_name, current_temp, true);
1021 any_failures = true;
1022 } else {
1023 value_accuracy_to_buf(value_buf, obj->current_temperature, current_accuracy);
1024 climate_value_row_(stream, obj, area, node, friendly_name, current_temp, value_buf);
1025 climate_failed_row_(stream, obj, area, node, friendly_name, current_temp, false);
1026 }
1027 }
1028 if (traits.has_feature_flags(climate::CLIMATE_SUPPORTS_CURRENT_HUMIDITY)) {
1029 std::string current_humidity = "current_humidity";
1030 if (std::isnan(obj->current_humidity)) {
1031 climate_failed_row_(stream, obj, area, node, friendly_name, current_humidity, true);
1032 any_failures = true;
1033 } else {
1034 value_accuracy_to_buf(value_buf, obj->current_humidity, 0);
1035 climate_value_row_(stream, obj, area, node, friendly_name, current_humidity, value_buf);
1036 climate_failed_row_(stream, obj, area, node, friendly_name, current_humidity, false);
1037 }
1038 }
1039 if (traits.has_feature_flags(climate::CLIMATE_SUPPORTS_TARGET_HUMIDITY)) {
1040 std::string target_humidity = "target_humidity";
1041 if (std::isnan(obj->target_humidity)) {
1042 climate_failed_row_(stream, obj, area, node, friendly_name, target_humidity, true);
1043 any_failures = true;
1044 } else {
1045 value_accuracy_to_buf(value_buf, obj->target_humidity, 0);
1046 climate_value_row_(stream, obj, area, node, friendly_name, target_humidity, value_buf);
1047 climate_failed_row_(stream, obj, area, node, friendly_name, target_humidity, false);
1048 }
1049 }
1050 if (traits.has_feature_flags(climate::CLIMATE_SUPPORTS_TWO_POINT_TARGET_TEMPERATURE |
1052 std::string target_temp_low = "target_temperature_low";
1053 value_accuracy_to_buf(value_buf, obj->target_temperature_low, target_accuracy);
1054 climate_value_row_(stream, obj, area, node, friendly_name, target_temp_low, value_buf);
1055 std::string target_temp_high = "target_temperature_high";
1056 value_accuracy_to_buf(value_buf, obj->target_temperature_high, target_accuracy);
1057 climate_value_row_(stream, obj, area, node, friendly_name, target_temp_high, value_buf);
1058 } else {
1059 std::string target_temp = "target_temperature";
1060 value_accuracy_to_buf(value_buf, obj->target_temperature, target_accuracy);
1061 climate_value_row_(stream, obj, area, node, friendly_name, target_temp, value_buf);
1062 }
1063 if (traits.has_feature_flags(climate::CLIMATE_SUPPORTS_ACTION)) {
1064 std::string climate_trait_category = "action";
1065 const auto *climate_trait_value = climate::climate_action_to_string(obj->action);
1066 climate_setting_row_(stream, obj, area, node, friendly_name, climate_trait_category, climate_trait_value);
1067 }
1068 if (traits.get_supports_fan_modes()) {
1069 std::string climate_trait_category = "fan_mode";
1070 if (obj->fan_mode.has_value()) {
1071 const auto *climate_trait_value = climate::climate_fan_mode_to_string(obj->fan_mode.value());
1072 climate_setting_row_(stream, obj, area, node, friendly_name, climate_trait_category, climate_trait_value);
1073 climate_failed_row_(stream, obj, area, node, friendly_name, climate_trait_category, false);
1074 } else {
1075 climate_failed_row_(stream, obj, area, node, friendly_name, climate_trait_category, true);
1076 any_failures = true;
1077 }
1078 }
1079 if (traits.get_supports_presets()) {
1080 std::string climate_trait_category = "preset";
1081 if (obj->preset.has_value()) {
1082 const auto *climate_trait_value = climate::climate_preset_to_string(obj->preset.value());
1083 climate_setting_row_(stream, obj, area, node, friendly_name, climate_trait_category, climate_trait_value);
1084 climate_failed_row_(stream, obj, area, node, friendly_name, climate_trait_category, false);
1085 } else {
1086 climate_failed_row_(stream, obj, area, node, friendly_name, climate_trait_category, true);
1087 any_failures = true;
1088 }
1089 }
1090 if (traits.get_supports_swing_modes()) {
1091 std::string climate_trait_category = "swing_mode";
1092 const auto *climate_trait_value = climate::climate_swing_mode_to_string(obj->swing_mode);
1093 climate_setting_row_(stream, obj, area, node, friendly_name, climate_trait_category, climate_trait_value);
1094 }
1095 std::string all_climate_category = "all";
1096 climate_failed_row_(stream, obj, area, node, friendly_name, all_climate_category, any_failures);
1097}
1098#endif
1099
1100} // namespace esphome::prometheus
1101
1102#endif
const StringRef & get_name() const
Get the name of this Application set by pre_setup().
const StringRef & get_friendly_name() const
Get the friendly name of this Application set by pre_setup().
const char * get_area() const
Get the area of this Application set by pre_setup().
void number_type_(AsyncResponseStream *stream)
Return the type for prometheus.
void add_friendly_name_label_(AsyncResponseStream *stream, std::string &friendly_name)
void handle_update_state_(AsyncResponseStream *stream, update::UpdateState state)
void climate_setting_row_(AsyncResponseStream *stream, climate::Climate *obj, std::string &area, std::string &node, std::string &friendly_name, std::string &setting, const LogString *setting_value)
void event_type_(AsyncResponseStream *stream)
Return the type for prometheus.
void media_player_row_(AsyncResponseStream *stream, media_player::MediaPlayer *obj, std::string &area, std::string &node, std::string &friendly_name)
Return the media player state as prometheus data point.
void light_type_(AsyncResponseStream *stream)
Return the type for prometheus.
void text_type_(AsyncResponseStream *stream)
Return the type for prometheus.
void update_entity_row_(AsyncResponseStream *stream, update::UpdateEntity *obj, std::string &area, std::string &node, std::string &friendly_name)
Return the update state and info as prometheus data point.
std::map< EntityBase *, std::string > relabel_map_id_
void fan_row_(AsyncResponseStream *stream, fan::Fan *obj, std::string &area, std::string &node, std::string &friendly_name)
Return the fan state as prometheus data point.
void climate_type_(AsyncResponseStream *stream)
Return the type for prometheus.
void binary_sensor_type_(AsyncResponseStream *stream)
Return the type for prometheus.
void switch_row_(AsyncResponseStream *stream, switch_::Switch *obj, std::string &area, std::string &node, std::string &friendly_name)
Return the switch values state as prometheus data point.
std::map< EntityBase *, std::string > relabel_map_name_
void sensor_row_(AsyncResponseStream *stream, sensor::Sensor *obj, std::string &area, std::string &node, std::string &friendly_name)
Return the sensor state as prometheus data point.
void light_row_(AsyncResponseStream *stream, light::LightState *obj, std::string &area, std::string &node, std::string &friendly_name)
Return the light values state as prometheus data point.
void climate_row_(AsyncResponseStream *stream, climate::Climate *obj, std::string &area, std::string &node, std::string &friendly_name)
Return the climate state as prometheus data point.
void update_entity_type_(AsyncResponseStream *stream)
Return the type for prometheus.
void climate_failed_row_(AsyncResponseStream *stream, climate::Climate *obj, std::string &area, std::string &node, std::string &friendly_name, std::string &category, bool is_failed_value)
void binary_sensor_row_(AsyncResponseStream *stream, binary_sensor::BinarySensor *obj, std::string &area, std::string &node, std::string &friendly_name)
Return the binary sensor state as prometheus data point.
void number_row_(AsyncResponseStream *stream, number::Number *obj, std::string &area, std::string &node, std::string &friendly_name)
Return the number state as prometheus data point.
void valve_type_(AsyncResponseStream *stream)
Return the type for prometheus.
void switch_type_(AsyncResponseStream *stream)
Return the type for prometheus.
void media_player_type_(AsyncResponseStream *stream)
Return the type for prometheus.
void print_metric_labels_(AsyncResponseStream *stream, const __FlashStringHelper *metric_name, EntityBase *obj, std::string &area, std::string &node, std::string &friendly_name)
Print metric name and common labels (id, area, node, friendly_name, name)
void event_row_(AsyncResponseStream *stream, event::Event *obj, std::string &area, std::string &node, std::string &friendly_name)
Return the event values state as prometheus data point.
void text_sensor_type_(AsyncResponseStream *stream)
Return the type for prometheus.
std::string relabel_id_(EntityBase *obj)
void text_sensor_row_(AsyncResponseStream *stream, text_sensor::TextSensor *obj, std::string &area, std::string &node, std::string &friendly_name)
Return the text sensor values state as prometheus data point.
void add_area_label_(AsyncResponseStream *stream, std::string &area)
void select_row_(AsyncResponseStream *stream, select::Select *obj, std::string &area, std::string &node, std::string &friendly_name)
Return the select state as prometheus data point.
std::string relabel_name_(EntityBase *obj)
void cover_type_(AsyncResponseStream *stream)
Return the type for prometheus.
void select_type_(AsyncResponseStream *stream)
Return the type for prometheus.
void add_node_label_(AsyncResponseStream *stream, std::string &node)
void handleRequest(AsyncWebServerRequest *req) override
void text_row_(AsyncResponseStream *stream, text::Text *obj, std::string &area, std::string &node, std::string &friendly_name)
Return the text values state as prometheus data point.
void cover_row_(AsyncResponseStream *stream, cover::Cover *obj, std::string &area, std::string &node, std::string &friendly_name)
Return the cover values state as prometheus data point.
void lock_type_(AsyncResponseStream *stream)
Return the type for prometheus.
void valve_row_(AsyncResponseStream *stream, valve::Valve *obj, std::string &area, std::string &node, std::string &friendly_name)
Return the valve state as prometheus data point.
void climate_value_row_(AsyncResponseStream *stream, climate::Climate *obj, std::string &area, std::string &node, std::string &friendly_name, std::string &category, const char *climate_value)
void fan_type_(AsyncResponseStream *stream)
Return the type for prometheus.
void sensor_type_(AsyncResponseStream *stream)
Return the type for prometheus.
void lock_row_(AsyncResponseStream *stream, lock::Lock *obj, std::string &area, std::string &node, std::string &friendly_name)
Return the lock values state as prometheus data point.
float target_humidity
Definition climate.h:19
bool state
Definition fan.h:2
const LogString * climate_action_to_string(ClimateAction action)
Convert the given ClimateAction to a human-readable string.
@ CLIMATE_SUPPORTS_CURRENT_HUMIDITY
@ CLIMATE_SUPPORTS_TWO_POINT_TARGET_TEMPERATURE
@ CLIMATE_SUPPORTS_CURRENT_TEMPERATURE
@ CLIMATE_REQUIRES_TWO_POINT_TARGET_TEMPERATURE
const LogString * climate_swing_mode_to_string(ClimateSwingMode swing_mode)
Convert the given ClimateSwingMode to a human-readable string.
const LogString * climate_preset_to_string(ClimatePreset preset)
Convert the given PresetMode to a human-readable string.
const LogString * climate_fan_mode_to_string(ClimateFanMode fan_mode)
Convert the given ClimateFanMode to a human-readable string.
const LogString * climate_mode_to_string(ClimateMode mode)
Convert the given ClimateMode to a human-readable string.
static float float b
@ BRIGHTNESS
Master brightness of the light can be controlled.
@ RGB
Color can be controlled using RGB format (includes a brightness control for the color).
@ WHITE
Brightness of white channel can be controlled separately from other channels.
const char * media_player_state_to_string(MediaPlayerState state)
const LogString * valve_operation_to_str(ValveOperation op)
Definition valve.cpp:28
size_t value_accuracy_to_buf(std::span< char, VALUE_ACCURACY_MAX_LEN > buf, float value, int8_t accuracy_decimals)
Format value with accuracy to buffer, returns chars written (excluding null)
Definition helpers.cpp:474
Application App
Global storage of Application pointer - only one Application can exist.