nicer graphs i hope

This commit is contained in:
2026-08-30 15:04:40 +02:00
parent 21cf23088c
commit a5ac054f57
4 changed files with 59 additions and 19 deletions
+3 -2
View File
@@ -6,8 +6,9 @@ with a provisioned dashboard.
## Metrics
- For every room and zone: available lights, shining lights, percentages shining,
off, and unavailable, plus average brightness of the shining lights.
- For every room and zone: available, shining, off, and unavailable light counts;
percentages shining, off, and unavailable; plus average brightness of the shining
lights.
- For every temperature and illuminance sensor: availability and its latest reading,
labelled with its room and zones.
+48 -17
View File
@@ -4,46 +4,77 @@
"graphTooltip": 1,
"panels": [
{
"type": "timeseries", "title": "Lights shining", "id": 1,
"gridPos": {"h": 8, "w": 12, "x": 0, "y": 0},
"fieldConfig": {"defaults": {"unit": "percent", "min": 0, "max": 100}, "overrides": []},
"type": "timeseries", "title": "$group_type: $group", "id": 1,
"repeat": "group", "repeatDirection": "v",
"gridPos": {"h": 10, "w": 24, "x": 0, "y": 0},
"fieldConfig": {
"defaults": {
"decimals": 0,
"min": 0,
"custom": {"drawStyle": "bars", "barAlignment": 0, "fillOpacity": 80, "lineWidth": 1, "stacking": {"mode": "normal", "group": "lights"}}
},
"overrides": [
{"matcher": {"id": "byName", "options": "Unavailable"}, "properties": [{"id": "color", "value": {"mode": "fixed", "fixedColor": "dark-red"}}]},
{"matcher": {"id": "byName", "options": "Off"}, "properties": [{"id": "color", "value": {"mode": "fixed", "fixedColor": "dark-gray"}}]},
{"matcher": {"id": "byName", "options": "On"}, "properties": [{"id": "color", "value": {"mode": "fixed", "fixedColor": "yellow"}}]},
{"matcher": {"id": "byName", "options": "Intensity"}, "properties": [
{"id": "unit", "value": "percent"}, {"id": "max", "value": 100},
{"id": "custom.axisPlacement", "value": "right"}, {"id": "custom.drawStyle", "value": "line"},
{"id": "custom.fillOpacity", "value": 0}, {"id": "custom.lineWidth", "value": 3},
{"id": "custom.stacking", "value": {"mode": "none", "group": "intensity"}},
{"id": "color", "value": {"mode": "fixed", "fixedColor": "green"}}
]}
]
},
"targets": [
{"expr": "hue_group_lights_shining_percent", "legendFormat": "shining — {{group_type}}: {{group}}", "refId": "A"},
{"expr": "hue_group_lights_off_percent", "legendFormat": "off — {{group_type}}: {{group}}", "refId": "B"},
{"expr": "hue_group_lights_unavailable_percent", "legendFormat": "unavailable — {{group_type}}: {{group}}", "refId": "C"}
{"expr": "hue_group_lights_unavailable{group_type=\"$group_type\", group=~\"$group\"}", "legendFormat": "Unavailable", "refId": "A"},
{"expr": "hue_group_lights_off{group_type=\"$group_type\", group=~\"$group\"}", "legendFormat": "Off", "refId": "B"},
{"expr": "hue_group_lights_shining{group_type=\"$group_type\", group=~\"$group\"}", "legendFormat": "On", "refId": "C"},
{"expr": "hue_group_average_brightness_percent{group_type=\"$group_type\", group=~\"$group\"}", "legendFormat": "Intensity", "refId": "D"}
]
},
{
"type": "timeseries", "title": "Average intensity of shining lights", "id": 2,
"gridPos": {"h": 8, "w": 12, "x": 12, "y": 0},
"fieldConfig": {"defaults": {"unit": "percent", "min": 0, "max": 100}, "overrides": []},
"targets": [{"expr": "hue_group_average_brightness_percent", "legendFormat": "{{group_type}}: {{group}}", "refId": "A"}]
},
{
"type": "timeseries", "title": "Temperature", "id": 3,
"gridPos": {"h": 8, "w": 12, "x": 0, "y": 8},
"gridPos": {"h": 8, "w": 12, "x": 0, "y": 10},
"fieldConfig": {"defaults": {"unit": "celsius"}, "overrides": []},
"targets": [{"expr": "hue_temperature_celsius", "legendFormat": "{{sensor}} ({{room}})", "refId": "A"}]
},
{
"type": "timeseries", "title": "Light intensity", "id": 4,
"gridPos": {"h": 8, "w": 12, "x": 12, "y": 8},
"gridPos": {"h": 8, "w": 12, "x": 12, "y": 10},
"fieldConfig": {"defaults": {"unit": "lux"}, "overrides": []},
"targets": [{"expr": "hue_light_level_lux", "legendFormat": "{{sensor}} ({{room}})", "refId": "A"}]
},
{
"type": "table", "title": "Unavailable sensors", "id": 5,
"gridPos": {"h": 7, "w": 24, "x": 0, "y": 16},
"gridPos": {"h": 7, "w": 24, "x": 0, "y": 18},
"targets": [{"expr": "hue_sensor_available == 0", "format": "table", "instant": true, "refId": "A"}]
}
],
"refresh": "30s",
"schemaVersion": 42,
"tags": ["hue"],
"templating": {"list": []},
"templating": {"list": [
{
"name": "group_type", "label": "Show", "type": "custom",
"query": "room,zone", "options": [
{"selected": true, "text": "room", "value": "room"},
{"selected": false, "text": "zone", "value": "zone"}
],
"current": {"selected": true, "text": "room", "value": "room"}
},
{
"name": "group", "label": "Room / zone", "type": "query",
"datasource": {"type": "prometheus", "uid": "victoriametrics"},
"definition": "label_values(hue_group_lights_available{group_type=\"$group_type\"}, group)",
"query": {"query": "label_values(hue_group_lights_available{group_type=\"$group_type\"}, group)", "refId": "variable-group"},
"refresh": 1, "sort": 1, "multi": true, "includeAll": true,
"allValue": ".+", "current": {"selected": true, "text": "All", "value": "$__all"}
}
]},
"time": {"from": "now-24h", "to": "now"},
"timezone": "browser",
"title": "Philips Hue",
"uid": "philips-hue-local",
"version": 1
"version": 2
}
+6
View File
@@ -92,6 +92,10 @@ class Collector:
"# TYPE hue_group_lights_available gauge",
"# HELP hue_group_lights_shining Number of connected lights that are on.",
"# TYPE hue_group_lights_shining gauge",
"# HELP hue_group_lights_off Number of connected lights that are off.",
"# TYPE hue_group_lights_off gauge",
"# HELP hue_group_lights_unavailable Number of configured lights that are disconnected.",
"# TYPE hue_group_lights_unavailable gauge",
"# HELP hue_group_lights_shining_percent Percentage of connected lights that are on.",
"# TYPE hue_group_lights_shining_percent gauge",
"# HELP hue_group_lights_off_percent Percentage of connected lights that are off.",
@@ -120,6 +124,8 @@ class Collector:
labels = {"group_type": kind, "group": group.get("metadata", {}).get("name", group["id"]), "group_id": group["id"]}
lines.append(_sample("hue_group_lights_available", len(lights), **labels))
lines.append(_sample("hue_group_lights_shining", len(shining), **labels))
lines.append(_sample("hue_group_lights_off", off, **labels))
lines.append(_sample("hue_group_lights_unavailable", unavailable, **labels))
lines.append(_sample("hue_group_lights_shining_percent", 100 * len(shining) / len(lights) if lights else 0, **labels))
lines.append(_sample("hue_group_lights_off_percent", 100 * off / len(lights) if lights else 0, **labels))
lines.append(_sample("hue_group_lights_unavailable_percent", 100 * unavailable / len(all_lights) if all_lights else 0, **labels))
+2
View File
@@ -35,6 +35,8 @@ class CollectorTests(unittest.TestCase):
def test_group_counts_only_connected_lights(self):
self.assertIn('hue_group_lights_available{group="Office",group_id="r1",group_type="room"} 1', self.metrics)
self.assertIn('hue_group_lights_off{group="Office",group_id="r1",group_type="room"} 0', self.metrics)
self.assertIn('hue_group_lights_unavailable{group="Office",group_id="r1",group_type="room"} 1', self.metrics)
self.assertIn('hue_group_lights_shining_percent{group="Office",group_id="r1",group_type="room"} 100.0', self.metrics)
self.assertIn('hue_group_lights_off_percent{group="Office",group_id="r1",group_type="room"} 0.0', self.metrics)
self.assertIn('hue_group_lights_unavailable_percent{group="Office",group_id="r1",group_type="room"} 50.0', self.metrics)