Closed gmoscalu closed 1 week ago
Hey @gmoscalu ,
i got the same problem with the script. But i could fixed it by reading the manual: https://shelly-api-docs.shelly.cloud/gen2/ComponentsAndServices/PM1/
The constant is CASE-SENSITIVE
so try this:
const monitored_switches = ["PM1:0"]
And the Temperature is not a valid Metric of the PM mini. Here is my modified Script:
/*
* This script exposes a "/status" endpoint that returns Prometheus metrics that can be scraped.
* It will be reachable under "<ip>/script/<id>/metrics". Id will be 1 if this is your first script.
*
* Example Prometheus config:
*
* scrape_configs:
* - job_name: 'shelly'
* metrics_path: /script/1/metrics
* static_configs:
* - targets: ['<ip>']
*
* Replace <ip> with the ip address of the device and adjust the script id if needed.
*
* If you use Grafana to display metrics scraped, you can give a try to the example dashboard in prometheus-grafana-example-dashboard.json
* available via the url https://raw.githubusercontent.com/ALLTERCO/shelly-script-examples/main/prometheus-grafana-example-dashboard.json
*
* Note: This script assumes you have one switch, but you can configure that in the Configuration section
*/
// ---------------------------------------------------------------------------------------------------------------------
// Configuration (you can change / adapt here)
// ---------------------------------------------------------------------------------------------------------------------
// Prefix added to all metrics name
const metric_prefix = "shelly_"
// url of metrics. will be used for the last part of "<ip>/script/<id>/<url>"
// where ip = your plug ip/hostname; id the script id or number (1 if this is the first); url the value below
const url = "metrics"
// List of internal switch to monitor using the shelly's id naming scheme in the form of switch:<id> (ex switch:0)
const monitored_switches = ["PM1:0"]
// ---------------------------------------------------------------------------------------------------------------------
// Prometheus exporter
// ---------------------------------------------------------------------------------------------------------------------
const TYPE_GAUGE = "gauge"
const TYPE_COUNTER = "counter"
var info = Shelly.getDeviceInfo();
function promLabel(label, value) {
return [label, "=", '"', value, '"'].join("");
}
// Will be added to every metrics
var defaultLabels = [
["name", info.name],
["id", info.id],
["mac", info.mac],
["app", info.app]
]
.map(function (data) {
return promLabel(data[0], data[1]);
});
/**
* Generate one metric output with all the shenanigans around it
* @param name The name of the metrics (Will be prefixed by metric_prefix value)
* @param type One of the TYPE_* of metrics. Usually Counter, Gauge, Histogram (not supported yes)
* @param specificLabels Array of labels generated by promLabel() specific to this metric.
* @param description An Human description of the metric
* @param value The actual metric numeric value
* @returns {string} The metric string to include in final response
*/
function printPrometheusMetric(name, type, specificLabels, description, value) {
return [
"# HELP ", metric_prefix, name, " ", description, "\n",
"# HELP ", metric_prefix, name, " ", type, "\n",
metric_prefix, name, "{", defaultLabels.join(","), specificLabels.length > 0 ? "," : "", specificLabels.join(","), "}", " ", value, "\n\n"
].join("");
}
/**
* HTTP handler that will be called when the url will be accessed
* @param request
* @param response
*/
function httpServerHandler(request, response) {
response.body = [
generateMetricsForSystem(),
monitored_switches.map(function (switch_string_id) {
return generateMetricsForSwitch(switch_string_id)
}).join("")
].join("")
response.code = 200;
response.send();
}
/**
* Generate metrics for the system part
* @returns {string}
*/
function generateMetricsForSystem() {
const sys = Shelly.getComponentStatus("sys")
return [
printPrometheusMetric("uptime_seconds", TYPE_COUNTER, [], "power level in watts", sys.uptime),
printPrometheusMetric("ram_size_bytes", TYPE_GAUGE, [], "Internal board RAM size in bytes", sys.ram_size),
printPrometheusMetric("ram_free_bytes", TYPE_GAUGE, [], "Internal board free RAM size in bytes", sys.ram_free)
].join("")
}
/**
* generate metrics for one switch with the name given as parameter
* @returns {string}
*/
function generateMetricsForSwitch(string_id) {
const pm = Shelly.getComponentStatus(string_id);
return [
printPrometheusMetric("pm_power_watts", TYPE_GAUGE, [promLabel("pm", pm.id)], "Instant power consumption in watts", pm.apower),
printPrometheusMetric("pm_voltage_volts", TYPE_GAUGE, [promLabel("pm", pm.id)], "Instant voltage in volts", pm.voltage),
printPrometheusMetric("pm_current_amperes", TYPE_GAUGE, [promLabel("pm", pm.id)], "Instant current in amperes", pm.current),
printPrometheusMetric("pm_returned_energy_total", TYPE_COUNTER, [promLabel("pm", pm.id)], "Total returned energy consumed in Watt-hours", pm.ret_aenergy.total),
printPrometheusMetric("pm_power_total", TYPE_COUNTER, [promLabel("pm", pm.id)], "accumulated energy consumed in watts hours", pm.aenergy.total)
].join("");
}
HTTPServer.registerEndpoint(url, httpServerHandler);
Thanks a lot @raikel93 !
Your script seems to work very well!
Describe the bug Script gives an error not the desired output.
To Reproduce Steps to reproduce the behavior:
const monitored_switches = ["pm1:0"]
Expected behavior As "promised" by the script, i hoped to be able to scrape these devices (10 of them) directly from Prometheus, not going through the json_exporter tool...
Screenshots Postman:
Console:
Device and script details (please complete the following information):
Additional context Add any other context about the problem here.