mirror of
https://github.com/arendst/Tasmota.git
synced 2025-07-25 19:56:30 +00:00
sensor data to prometheus metrics
This commit is contained in:
parent
47b99764ea
commit
3d6dd8ff87
@ -22,17 +22,74 @@
|
|||||||
* Prometheus support
|
* Prometheus support
|
||||||
\*********************************************************************************************/
|
\*********************************************************************************************/
|
||||||
|
|
||||||
#define XSNS_75 75
|
#define XSNS_75 75
|
||||||
|
|
||||||
|
const char *UnitfromType(const char *type)
|
||||||
|
{
|
||||||
|
if (strcmp(type, "time") == 0)
|
||||||
|
{
|
||||||
|
return "_seconds";
|
||||||
|
}
|
||||||
|
if (strcmp(type, "temperature") == 0 || strcmp(type, "dewpoint") == 0)
|
||||||
|
{
|
||||||
|
return "_celsius";
|
||||||
|
}
|
||||||
|
if (strcmp(type, "pressure") == 0)
|
||||||
|
{
|
||||||
|
return "_hpa";
|
||||||
|
}
|
||||||
|
if (strcmp(type, "voltage") == 0)
|
||||||
|
{
|
||||||
|
return "_volts";
|
||||||
|
}
|
||||||
|
if (strcmp(type, "current") == 0)
|
||||||
|
{
|
||||||
|
return "_amperes";
|
||||||
|
}
|
||||||
|
if (strcmp(type, "mass") == 0)
|
||||||
|
{
|
||||||
|
return "_grams";
|
||||||
|
}
|
||||||
|
if (strcmp(type, "carbondioxide") == 0)
|
||||||
|
{
|
||||||
|
return "_ppm";
|
||||||
|
}
|
||||||
|
if (strcmp(type, "humidity") == 0)
|
||||||
|
{
|
||||||
|
return "_percentage";
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *FormatMetricName(const char *metric)
|
||||||
|
{
|
||||||
|
char *formated = (char *)malloc(strlen(metric) + 1);
|
||||||
|
uint32_t cnt = 0;
|
||||||
|
for (cnt; cnt < strlen(metric) + 1; cnt++)
|
||||||
|
{
|
||||||
|
if (metric[cnt] == ' ')
|
||||||
|
{ //replace space with
|
||||||
|
formated[cnt] = '_';
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
formated[cnt] = tolower(metric[cnt]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return formated;
|
||||||
|
}
|
||||||
|
|
||||||
void HandleMetrics(void)
|
void HandleMetrics(void)
|
||||||
{
|
{
|
||||||
if (!HttpCheckPriviledgedAccess()) { return; }
|
if (!HttpCheckPriviledgedAccess())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_HTTP "Prometheus"));
|
AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_HTTP "Prometheus"));
|
||||||
|
|
||||||
WSContentBegin(200, CT_PLAIN);
|
WSContentBegin(200, CT_PLAIN);
|
||||||
|
|
||||||
|
|
||||||
char parameter[FLOATSZ];
|
char parameter[FLOATSZ];
|
||||||
|
|
||||||
// Pseudo-metric providing metadata about the running firmware version.
|
// Pseudo-metric providing metadata about the running firmware version.
|
||||||
@ -42,22 +99,24 @@ void HandleMetrics(void)
|
|||||||
WSContentSend_P(PSTR("# TYPE tasmota_boot_count counter\ntasmota_boot_count %d\n"), Settings.bootcount);
|
WSContentSend_P(PSTR("# TYPE tasmota_boot_count counter\ntasmota_boot_count %d\n"), Settings.bootcount);
|
||||||
WSContentSend_P(PSTR("# TYPE tasmota_flash_writes_total counter\ntasmota_flash_writes_total %d\n"), Settings.save_flag);
|
WSContentSend_P(PSTR("# TYPE tasmota_flash_writes_total counter\ntasmota_flash_writes_total %d\n"), Settings.save_flag);
|
||||||
|
|
||||||
|
|
||||||
// Pseudo-metric providing metadata about the WiFi station.
|
// Pseudo-metric providing metadata about the WiFi station.
|
||||||
WSContentSend_P(PSTR("# TYPE tasmota_wifi_station_info gauge\ntasmota_wifi_station_info{bssid=\"%s\",ssid=\"%s\"} 1\n"), WiFi.BSSIDstr().c_str(), WiFi.SSID().c_str());
|
WSContentSend_P(PSTR("# TYPE tasmota_wifi_station_info gauge\ntasmota_wifi_station_info{bssid=\"%s\",ssid=\"%s\"} 1\n"), WiFi.BSSIDstr().c_str(), WiFi.SSID().c_str());
|
||||||
|
|
||||||
// Wi-Fi Signal strength
|
// Wi-Fi Signal strength
|
||||||
WSContentSend_P(PSTR("# TYPE tasmota_wifi_station_signal_dbm gauge\ntasmota_wifi_station_signal_dbm{mac_address=\"%s\"} %d\n"), WiFi.BSSIDstr().c_str(), WiFi.RSSI());
|
WSContentSend_P(PSTR("# TYPE tasmota_wifi_station_signal_dbm gauge\ntasmota_wifi_station_signal_dbm{mac_address=\"%s\"} %d\n"), WiFi.BSSIDstr().c_str(), WiFi.RSSI());
|
||||||
|
|
||||||
if (!isnan(TasmotaGlobal.temperature_celsius)) {
|
if (!isnan(TasmotaGlobal.temperature_celsius))
|
||||||
|
{
|
||||||
dtostrfd(TasmotaGlobal.temperature_celsius, Settings.flag2.temperature_resolution, parameter);
|
dtostrfd(TasmotaGlobal.temperature_celsius, Settings.flag2.temperature_resolution, parameter);
|
||||||
WSContentSend_P(PSTR("# TYPE tasmotaglobal_temperature_celsius gauge\ntasmotaglobal_temperature_celsius %s\n"), parameter);
|
WSContentSend_P(PSTR("# TYPE tasmotaglobal_temperature_celsius gauge\ntasmotaglobal_temperature_celsius %s\n"), parameter);
|
||||||
}
|
}
|
||||||
if (TasmotaGlobal.humidity != 0) {
|
if (TasmotaGlobal.humidity != 0)
|
||||||
|
{
|
||||||
dtostrfd(TasmotaGlobal.humidity, Settings.flag2.humidity_resolution, parameter);
|
dtostrfd(TasmotaGlobal.humidity, Settings.flag2.humidity_resolution, parameter);
|
||||||
WSContentSend_P(PSTR("# TYPE tasmotaglobal_humidity gauge\ntasmotaglobal_humidity %s\n"), parameter);
|
WSContentSend_P(PSTR("# TYPE tasmotaglobal_humidity gauge\ntasmotaglobal_humidity %s\n"), parameter);
|
||||||
}
|
}
|
||||||
if (TasmotaGlobal.pressure_hpa != 0) {
|
if (TasmotaGlobal.pressure_hpa != 0)
|
||||||
|
{
|
||||||
dtostrfd(TasmotaGlobal.pressure_hpa, Settings.flag2.pressure_resolution, parameter);
|
dtostrfd(TasmotaGlobal.pressure_hpa, Settings.flag2.pressure_resolution, parameter);
|
||||||
WSContentSend_P(PSTR("# TYPE tasmotaglobal_pressure_hpa gauge\ntasmotaglobal_pressure_hpa %s\n"), parameter);
|
WSContentSend_P(PSTR("# TYPE tasmotaglobal_pressure_hpa gauge\ntasmotaglobal_pressure_hpa %s\n"), parameter);
|
||||||
}
|
}
|
||||||
@ -75,24 +134,69 @@ void HandleMetrics(void)
|
|||||||
WSContentSend_P(PSTR("# TYPE energy_power_kilowatts_total counter\nenergy_power_kilowatts_total %s\n"), parameter);
|
WSContentSend_P(PSTR("# TYPE energy_power_kilowatts_total counter\nenergy_power_kilowatts_total %s\n"), parameter);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
for (uint32_t device = 0; device < TasmotaGlobal.devices_present; device++) {
|
for (uint32_t device = 0; device < TasmotaGlobal.devices_present; device++)
|
||||||
|
{
|
||||||
power_t mask = 1 << device;
|
power_t mask = 1 << device;
|
||||||
WSContentSend_P(PSTR("# TYPE relay%d_state gauge\nrelay%d_state %d\n"), device+1, device+1, (TasmotaGlobal.power & mask));
|
WSContentSend_P(PSTR("# TYPE relay%d_state gauge\nrelay%d_state %d\n"), device + 1, device + 1, (TasmotaGlobal.power & mask));
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
// Alternative method using the complete sensor JSON data
|
|
||||||
// For prometheus it may need to be decoded to # TYPE messages
|
|
||||||
ResponseClear();
|
ResponseClear();
|
||||||
MqttShowSensor();
|
MqttShowSensor();
|
||||||
char json[strlen(TasmotaGlobal.mqtt_data) +1];
|
char json[strlen(TasmotaGlobal.mqtt_data) + 1];
|
||||||
snprintf_P(json, sizeof(json), TasmotaGlobal.mqtt_data);
|
snprintf_P(json, sizeof(json), TasmotaGlobal.mqtt_data);
|
||||||
|
String jsonStr = json;
|
||||||
// Do your Prometheus specific processing here.
|
JsonParser parser((char *)jsonStr.c_str());
|
||||||
// Look at function DisplayAnalyzeJson() in file xdrv_13_display.ino as an example how to decode the JSON message
|
JsonParserObject root = parser.getRootObject();
|
||||||
|
if (root)
|
||||||
WSContentSend_P(json);
|
{ // did JSON parsing went ok?
|
||||||
*/
|
for (auto key1 : root)
|
||||||
|
{
|
||||||
|
JsonParserToken value1 = key1.getValue();
|
||||||
|
if (value1.isObject())
|
||||||
|
{
|
||||||
|
JsonParserObject Object2 = value1.getObject();
|
||||||
|
for (auto key2 : Object2)
|
||||||
|
{
|
||||||
|
JsonParserToken value2 = key2.getValue();
|
||||||
|
if (value2.isObject())
|
||||||
|
{
|
||||||
|
JsonParserObject Object3 = value2.getObject();
|
||||||
|
for (auto key3 : Object3)
|
||||||
|
{
|
||||||
|
const char *value = key3.getValue().getStr(nullptr);
|
||||||
|
if (value != nullptr && isdigit(value[0]))
|
||||||
|
{
|
||||||
|
const char *sensor = FormatMetricName(key2.getStr()); //cleanup sensor name
|
||||||
|
const char *type = FormatMetricName(key3.getStr()); //cleanup sensor type
|
||||||
|
const char *unit = UnitfromType(type); //grab base unit corresponding to type
|
||||||
|
WSContentSend_P(PSTR("# TYPE tasmota_sensors_%s%s gauge\ntasmota_sensors_%s%s{sensor=\"%s\"} %s\n"), type, unit, type, unit, sensor, value); //build metric as "# TYPE tasmota_sensors_%type%_%unit% gauge\ntasmotasensors_%type%_%unit%{sensor=%sensor%"} %value%""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
const char *value = value2.getStr(nullptr);
|
||||||
|
if (value != nullptr && isdigit(value[0]))
|
||||||
|
{
|
||||||
|
const char *sensor = FormatMetricName(key1.getStr());
|
||||||
|
const char *type = FormatMetricName(key2.getStr());
|
||||||
|
const char *unit = UnitfromType(type);
|
||||||
|
WSContentSend_P(PSTR("# TYPE tasmota_sensors_%s%s gauge\ntasmota_sensors_%s%s{sensor=\"%s\"} %s\n"), type, unit, type, unit, sensor, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
const char *value = value1.getStr(nullptr);
|
||||||
|
if (value != nullptr && isdigit(value[0] && strcmp(key1.getStr(), "Time") != 0))
|
||||||
|
{ //remove false 'time' metric
|
||||||
|
const char *sensor = FormatMetricName(key1.getStr());
|
||||||
|
WSContentSend_P(PSTR("# TYPE tasmota_sensors_%s gauge\ntasmota_sensors{sensor=\"%s\"} %s\n"), sensor, sensor, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
WSContentEnd();
|
WSContentEnd();
|
||||||
}
|
}
|
||||||
@ -105,12 +209,13 @@ bool Xsns75(uint8_t function)
|
|||||||
{
|
{
|
||||||
bool result = false;
|
bool result = false;
|
||||||
|
|
||||||
switch (function) {
|
switch (function)
|
||||||
case FUNC_WEB_ADD_HANDLER:
|
{
|
||||||
WebServer_on(PSTR("/metrics"), HandleMetrics);
|
case FUNC_WEB_ADD_HANDLER:
|
||||||
break;
|
WebServer_on(PSTR("/metrics"), HandleMetrics);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // USE_PROMETHEUS
|
#endif // USE_PROMETHEUS
|
||||||
|
Loading…
x
Reference in New Issue
Block a user