mirror of
https://github.com/esphome/esphome.git
synced 2025-10-01 17:42:22 +01:00
163 lines
4.0 KiB
C++
163 lines
4.0 KiB
C++
#include "esphome/core/log.h"
|
|
|
|
#include "statsd.h"
|
|
|
|
#ifdef USE_NETWORK
|
|
namespace esphome {
|
|
namespace statsd {
|
|
|
|
// send UDP packet if we reach 1Kb packed size
|
|
// this is needed since statsD does not support fragmented UDP packets
|
|
static const uint16_t SEND_THRESHOLD = 1024;
|
|
|
|
static const char *const TAG = "statsD";
|
|
|
|
void StatsdComponent::setup() {
|
|
#ifndef USE_ESP8266
|
|
this->sock_ = esphome::socket::socket(AF_INET, SOCK_DGRAM, 0);
|
|
|
|
struct sockaddr_in source;
|
|
source.sin_family = AF_INET;
|
|
source.sin_addr.s_addr = htonl(INADDR_ANY);
|
|
source.sin_port = htons(this->port_);
|
|
this->sock_->bind((struct sockaddr *) &source, sizeof(source));
|
|
|
|
this->destination_.sin_family = AF_INET;
|
|
this->destination_.sin_port = htons(this->port_);
|
|
this->destination_.sin_addr.s_addr = inet_addr(this->host_);
|
|
#endif
|
|
}
|
|
|
|
StatsdComponent::~StatsdComponent() {
|
|
#ifndef USE_ESP8266
|
|
if (!this->sock_) {
|
|
return;
|
|
}
|
|
this->sock_->close();
|
|
#endif
|
|
}
|
|
|
|
void StatsdComponent::dump_config() {
|
|
ESP_LOGCONFIG(TAG,
|
|
"statsD:\n"
|
|
" host: %s\n"
|
|
" port: %d",
|
|
this->host_, this->port_);
|
|
if (this->prefix_) {
|
|
ESP_LOGCONFIG(TAG, " prefix: %s", this->prefix_);
|
|
}
|
|
|
|
ESP_LOGCONFIG(TAG, " metrics:");
|
|
for (sensors_t s : this->sensors_) {
|
|
ESP_LOGCONFIG(TAG,
|
|
" - name: %s\n"
|
|
" type: %d",
|
|
s.name, s.type);
|
|
}
|
|
}
|
|
|
|
float StatsdComponent::get_setup_priority() const { return esphome::setup_priority::AFTER_WIFI; }
|
|
|
|
#ifdef USE_SENSOR
|
|
void StatsdComponent::register_sensor(const char *name, esphome::sensor::Sensor *sensor) {
|
|
sensors_t s;
|
|
s.name = name;
|
|
s.sensor = sensor;
|
|
s.type = TYPE_SENSOR;
|
|
this->sensors_.push_back(s);
|
|
}
|
|
#endif
|
|
|
|
#ifdef USE_BINARY_SENSOR
|
|
void StatsdComponent::register_binary_sensor(const char *name, esphome::binary_sensor::BinarySensor *binary_sensor) {
|
|
sensors_t s;
|
|
s.name = name;
|
|
s.binary_sensor = binary_sensor;
|
|
s.type = TYPE_BINARY_SENSOR;
|
|
this->sensors_.push_back(s);
|
|
}
|
|
#endif
|
|
|
|
void StatsdComponent::update() {
|
|
std::string out;
|
|
out.reserve(SEND_THRESHOLD);
|
|
|
|
for (sensors_t s : this->sensors_) {
|
|
double val = 0;
|
|
switch (s.type) {
|
|
#ifdef USE_SENSOR
|
|
case TYPE_SENSOR:
|
|
if (!s.sensor->has_state()) {
|
|
continue;
|
|
}
|
|
val = s.sensor->state;
|
|
break;
|
|
#endif
|
|
#ifdef USE_BINARY_SENSOR
|
|
case TYPE_BINARY_SENSOR:
|
|
if (!s.binary_sensor->has_state()) {
|
|
continue;
|
|
}
|
|
// map bool to double
|
|
if (s.binary_sensor->state) {
|
|
val = 1;
|
|
}
|
|
break;
|
|
#endif
|
|
default:
|
|
ESP_LOGE(TAG, "type not known, name: %s type: %d", s.name, s.type);
|
|
continue;
|
|
}
|
|
|
|
// statsD gauge:
|
|
// https://github.com/statsd/statsd/blob/master/docs/metric_types.md
|
|
// This implies you can't explicitly set a gauge to a negative number without first setting it to zero.
|
|
if (val < 0) {
|
|
if (this->prefix_) {
|
|
out.append(str_sprintf("%s.", this->prefix_));
|
|
}
|
|
out.append(str_sprintf("%s:0|g\n", s.name));
|
|
}
|
|
if (this->prefix_) {
|
|
out.append(str_sprintf("%s.", this->prefix_));
|
|
}
|
|
out.append(str_sprintf("%s:%f|g\n", s.name, val));
|
|
|
|
if (out.length() > SEND_THRESHOLD) {
|
|
this->send_(&out);
|
|
out.clear();
|
|
}
|
|
}
|
|
|
|
this->send_(&out);
|
|
}
|
|
|
|
void StatsdComponent::send_(std::string *out) {
|
|
if (out->empty()) {
|
|
return;
|
|
}
|
|
#ifdef USE_ESP8266
|
|
IPAddress ip;
|
|
ip.fromString(this->host_);
|
|
|
|
this->sock_.beginPacket(ip, this->port_);
|
|
this->sock_.write((const uint8_t *) out->c_str(), out->length());
|
|
this->sock_.endPacket();
|
|
|
|
#else
|
|
if (!this->sock_) {
|
|
return;
|
|
}
|
|
|
|
int n_bytes = this->sock_->sendto(out->c_str(), out->length(), 0, reinterpret_cast<sockaddr *>(&this->destination_),
|
|
sizeof(this->destination_));
|
|
if (n_bytes != out->length()) {
|
|
ESP_LOGE(TAG, "Failed to send UDP packed (%d of %d)", n_bytes, out->length());
|
|
}
|
|
#endif
|
|
}
|
|
|
|
} // namespace statsd
|
|
} // namespace esphome
|
|
#endif
|