ESPHome 2025.5.0
Loading...
Searching...
No Matches
statsd.cpp
Go to the documentation of this file.
1#include "esphome/core/log.h"
2
3#include "statsd.h"
4
5#ifdef USE_NETWORK
6namespace esphome {
7namespace statsd {
8
9// send UDP packet if we reach 1Kb packed size
10// this is needed since statsD does not support fragmented UDP packets
11static const uint16_t SEND_THRESHOLD = 1024;
12
13static const char *const TAG = "statsD";
14
16#ifndef USE_ESP8266
17 this->sock_ = esphome::socket::socket(AF_INET, SOCK_DGRAM, 0);
18
19 struct sockaddr_in source;
20 source.sin_family = AF_INET;
21 source.sin_addr.s_addr = htonl(INADDR_ANY);
22 source.sin_port = htons(this->port_);
23 this->sock_->bind((struct sockaddr *) &source, sizeof(source));
24
25 this->destination_.sin_family = AF_INET;
26 this->destination_.sin_port = htons(this->port_);
27 this->destination_.sin_addr.s_addr = inet_addr(this->host_);
28#endif
29}
30
32#ifndef USE_ESP8266
33 if (!this->sock_) {
34 return;
35 }
36 this->sock_->close();
37#endif
38}
39
41 ESP_LOGCONFIG(TAG, "statsD:");
42 ESP_LOGCONFIG(TAG, " host: %s", this->host_);
43 ESP_LOGCONFIG(TAG, " port: %d", this->port_);
44 if (this->prefix_) {
45 ESP_LOGCONFIG(TAG, " prefix: %s", this->prefix_);
46 }
47
48 ESP_LOGCONFIG(TAG, " metrics:");
49 for (sensors_t s : this->sensors_) {
50 ESP_LOGCONFIG(TAG, " - name: %s", s.name);
51 ESP_LOGCONFIG(TAG, " type: %d", s.type);
52 }
53}
54
56
57#ifdef USE_SENSOR
59 sensors_t s;
60 s.name = name;
61 s.sensor = sensor;
62 s.type = TYPE_SENSOR;
63 this->sensors_.push_back(s);
64}
65#endif
66
67#ifdef USE_BINARY_SENSOR
69 sensors_t s;
70 s.name = name;
71 s.binary_sensor = binary_sensor;
72 s.type = TYPE_BINARY_SENSOR;
73 this->sensors_.push_back(s);
74}
75#endif
76
78 std::string out;
79 out.reserve(SEND_THRESHOLD);
80
81 for (sensors_t s : this->sensors_) {
82 double val = 0;
83 switch (s.type) {
84#ifdef USE_SENSOR
85 case TYPE_SENSOR:
86 if (!s.sensor->has_state()) {
87 continue;
88 }
89 val = s.sensor->state;
90 break;
91#endif
92#ifdef USE_BINARY_SENSOR
93 case TYPE_BINARY_SENSOR:
94 if (!s.binary_sensor->has_state()) {
95 continue;
96 }
97 // map bool to double
98 if (s.binary_sensor->state) {
99 val = 1;
100 }
101 break;
102#endif
103 default:
104 ESP_LOGE(TAG, "type not known, name: %s type: %d", s.name, s.type);
105 continue;
106 }
107
108 // statsD gauge:
109 // https://github.com/statsd/statsd/blob/master/docs/metric_types.md
110 // This implies you can't explicitly set a gauge to a negative number without first setting it to zero.
111 if (val < 0) {
112 if (this->prefix_) {
113 out.append(str_sprintf("%s.", this->prefix_));
114 }
115 out.append(str_sprintf("%s:0|g\n", s.name));
116 }
117 if (this->prefix_) {
118 out.append(str_sprintf("%s.", this->prefix_));
119 }
120 out.append(str_sprintf("%s:%f|g\n", s.name, val));
121
122 if (out.length() > SEND_THRESHOLD) {
123 this->send_(&out);
124 out.clear();
125 }
126 }
127
128 this->send_(&out);
129}
130
131void StatsdComponent::send_(std::string *out) {
132 if (out->empty()) {
133 return;
134 }
135#ifdef USE_ESP8266
136 IPAddress ip;
137 ip.fromString(this->host_);
138
139 this->sock_.beginPacket(ip, this->port_);
140 this->sock_.write((const uint8_t *) out->c_str(), out->length());
141 this->sock_.endPacket();
142
143#else
144 if (!this->sock_) {
145 return;
146 }
147
148 int n_bytes = this->sock_->sendto(out->c_str(), out->length(), 0, reinterpret_cast<sockaddr *>(&this->destination_),
149 sizeof(this->destination_));
150 if (n_bytes != out->length()) {
151 ESP_LOGE(TAG, "Failed to send UDP packed (%d of %d)", n_bytes, out->length());
152 }
153#endif
154}
155
156} // namespace statsd
157} // namespace esphome
158#endif
Base class for all binary_sensor-type classes.
Base-class for all sensors.
Definition sensor.h:57
void register_sensor(const char *name, esphome::sensor::Sensor *sensor)
Definition statsd.cpp:58
void register_binary_sensor(const char *name, esphome::binary_sensor::BinarySensor *binary_sensor)
Definition statsd.cpp:68
float get_setup_priority() const override
Definition statsd.cpp:55
mopeka_std_values val[4]
const float AFTER_WIFI
For components that should be initialized after WiFi is connected.
Definition component.cpp:26
std::unique_ptr< Socket > socket(int domain, int type, int protocol)
Create a socket of the given domain, type and protocol.
struct { const char *name; sensor_type_t type; union { #ifdef USE_SENSOR esphome::sensor::Sensor *sensor;#endif #ifdef USE_BINARY_SENSOR esphome::binary_sensor::BinarySensor *binary_sensor;#endif };} sensors_t
Definition statsd.h:33
Providing packet encoding functions for exchanging data with a remote host.
Definition a01nyub.cpp:7
std::string str_sprintf(const char *fmt,...)
Definition helpers.cpp:323
struct in_addr sin_addr
Definition headers.h:65
sa_family_t sin_family
Definition headers.h:63
in_port_t sin_port
Definition headers.h:64