This is standard “Time series” visualization (actually I have migrated from “Graph (old)” which had the same issue), here is its JSON:
"id": 17,
"gridPos": {
"h": 9,
"w": 12,
"x": 12,
"y": 10
},
"type": "timeseries",
"title": "Humidity",
"datasource": {
"type": "mysql",
"uid": "atZYCuJnv"
},
"pluginVersion": "8.4.6",
"fieldConfig": {
"defaults": {
"custom": {
"drawStyle": "line",
"lineInterpolation": "smooth",
"barAlignment": 0,
"lineWidth": 1,
"fillOpacity": 10,
"gradientMode": "none",
"spanNulls": true,
"showPoints": "never",
"pointSize": 5,
"stacking": {
"mode": "none",
"group": "A"
},
"axisPlacement": "auto",
"axisLabel": "",
"scaleDistribution": {
"type": "linear"
},
"hideFrom": {
"tooltip": false,
"viz": false,
"legend": false
},
"thresholdsStyle": {
"mode": "off"
}
},
"color": {
"mode": "palette-classic"
},
"mappings": [],
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "green",
"value": null
},
{
"color": "red",
"value": 80
}
]
},
"links": [],
"unit": "humidity"
},
"overrides": [
{
"matcher": {
"id": "byName",
"options": "Cellar humidity"
},
"properties": [
{
"id": "custom.fillOpacity",
"value": 0
}
]
},
{
"__systemRef": "hideSeriesFrom",
"matcher": {
"id": "byNames",
"options": {
"mode": "exclude",
"names": [
"value Bath humidity"
],
"prefix": "All except:",
"readOnly": true
}
},
"properties": [
{
"id": "custom.hideFrom",
"value": {
"legend": false,
"tooltip": false,
"viz": true
}
}
]
}
]
},
"options": {
"tooltip": {
"mode": "multi",
"sort": "none"
},
"legend": {
"displayMode": "table",
"placement": "bottom",
"calcs": [
"lastNotNull",
"max",
"min"
]
}
},
"targets": [
{
"datasource": {
"type": "mysql",
"uid": "rtAYCuJnz"
},
"format": "time_series",
"group": [],
"metricColumn": "none",
"rawQuery": true,
"rawSql": "SELECT\n max(unix_timestamp((last_updated))) AS time,\n max(cast(state AS float)) AS value,\n 'Bath humidity' AS metrics\nFROM states\nWHERE $__timeFilter(last_updated)\nAND entity_id = 'sensor.bath_sensor_humidity'\nGROUP BY $__timeGroup(last_updated, $__interval)\nORDER BY $__timeGroup(last_updated, $__interval) ASC",
"refId": "B",
"select": [
[
{
"params": [
"event_id"
],
"type": "column"
}
]
],
"table": "events",
"timeColumn": "time_fired",
"timeColumnType": "timestamp",
"where": [
{
"name": "$__timeFilter",
"params": [],
"type": "macro"
}
]
},
{
"datasource": {
"type": "mysql",
"uid": "rtAYCuJnz"
},
"format": "time_series",
"group": [],
"metricColumn": "none",
"rawQuery": true,
"rawSql": "SELECT\n max(unix_timestamp((last_updated))) AS time,\n max(cast(state AS float)) AS value,\n 'Cellar humidity' AS metrics\nFROM states\nWHERE $__timeFilter(last_updated)\nAND entity_id = 'sensor.cellar_sensor_humidity'\nGROUP BY $__timeGroup(last_updated, $__interval)\nORDER BY $__timeGroup(last_updated, $__interval) ASC",
"refId": "D",
"select": [
[
{
"params": [
"event_id"
],
"type": "column"
}
]
],
"table": "events",
"timeColumn": "time_fired",
"timeColumnType": "timestamp",
"where": [
{
"name": "$__timeFilter",
"params": [],
"type": "macro"
}
]
},
{
"datasource": {
"type": "mysql",
"uid": "rtAYCuJnz"
},
"format": "time_series",
"group": [],
"metricColumn": "none",
"rawQuery": true,
"rawSql": "SELECT\n max(unix_timestamp((last_updated))) AS time,\n max(cast(state AS float)) AS value,\n 'Shed humidity' AS metrics\nFROM states\nWHERE $__timeFilter(last_updated)\nAND entity_id = 'sensor.shed_sensor_humidity'\nGROUP BY $__timeGroup(last_updated, $__interval)\nORDER BY $__timeGroup(last_updated, $__interval) ASC",
"refId": "F",
"select": [
[
{
"params": [
"event_id"
],
"type": "column"
}
]
],
"table": "events",
"timeColumn": "time_fired",
"timeColumnType": "timestamp",
"where": [
{
"name": "$__timeFilter",
"params": [],
"type": "macro"
}
]
}
]
}
CSV file:
"Time","value Bath humidity"
2022-04-22 15:23:37,53.2 %H
2022-04-22 15:30:39,53.5 %H
2022-04-22 15:35:32,53.5 %H
2022-04-22 16:06:36,53.2 %H
2022-04-22 16:22:54,52.6 %H
2022-04-22 16:34:09,52.6 %H
2022-04-22 17:22:00,52.2 %H
As you see, Grafana suggests the same label for CSV column as it is displayed in legend.