Administration

Monitoring

The control server exposes a Prometheus-compatible metrics server endpoint at /metrics. These metrics can be used to monitor the system’s health, machine status, and usage patterns.

A pre-built Grafana dashboard is provided for visualizing these metrics.

An example response from the metrics endpoint is:

# HELP python_gc_objects_collected_total Objects collected during gc
# TYPE python_gc_objects_collected_total counter
python_gc_objects_collected_total{generation="0"} 11253.0
python_gc_objects_collected_total{generation="1"} 23526.0
python_gc_objects_collected_total{generation="2"} 4120.0
# HELP python_gc_objects_uncollectable_total Uncollectable objects found during GC
# TYPE python_gc_objects_uncollectable_total counter
python_gc_objects_uncollectable_total{generation="0"} 0.0
python_gc_objects_uncollectable_total{generation="1"} 0.0
python_gc_objects_uncollectable_total{generation="2"} 0.0
# HELP python_gc_collections_total Number of times this generation was collected
# TYPE python_gc_collections_total counter
python_gc_collections_total{generation="0"} 248.0
python_gc_collections_total{generation="1"} 22.0
python_gc_collections_total{generation="2"} 2.0
# HELP python_info Python platform information
# TYPE python_info gauge
python_info{implementation="CPython",major="3",minor="12",patchlevel="7",version="3.12.7"} 1.0
# HELP process_virtual_memory_bytes Virtual memory size in bytes.
# TYPE process_virtual_memory_bytes gauge
process_virtual_memory_bytes 8.1723392e+07
# HELP process_resident_memory_bytes Resident memory size in bytes.
# TYPE process_resident_memory_bytes gauge
process_resident_memory_bytes 7.1622656e+07
# HELP process_start_time_seconds Start time of the process since unix epoch in seconds.
# TYPE process_start_time_seconds gauge
process_start_time_seconds 1.73115012004e+09
# HELP process_cpu_seconds_total Total user and system CPU time spent in seconds.
# TYPE process_cpu_seconds_total counter
process_cpu_seconds_total 3.79
# HELP process_open_fds Number of open file descriptors.
# TYPE process_open_fds gauge
process_open_fds 6.0
# HELP process_max_fds Maximum number of open file descriptors.
# TYPE process_max_fds gauge
process_max_fds 1024.0
# HELP machine_config_load_timestamp The timestamp when the machine config was loaded
# TYPE machine_config_load_timestamp gauge
machine_config_load_timestamp 1.689477248e+09
# HELP user_config_load_timestamp The timestamp when the users config was loaded
# TYPE user_config_load_timestamp gauge
user_config_load_timestamp 1.689477248e+09
# HELP user_config_file_mtime The modification time of the users config file
# TYPE user_config_file_mtime gauge
user_config_file_mtime 1.689477248e+09
# HELP app_start_timestamp The timestamp when the server app started
# TYPE app_start_timestamp gauge
app_start_timestamp 1.689477248e+09
# HELP user_count The number of users configured
# TYPE user_count gauge
user_count 4.0
# HELP fob_count The number of fobs configured
# TYPE fob_count gauge
fob_count 4.0
# HELP machine_relay_state The state of the machine relay
# TYPE machine_relay_state gauge
machine_relay_state{display_name="Metal Mill",machine_name="metal-mill"} 0.0
machine_relay_state{display_name="hammer",machine_name="hammer"} 0.0
machine_relay_state{display_name="permissive-lathe",machine_name="permissive-lathe"} 0.0
machine_relay_state{display_name="restrictive-lathe",machine_name="restrictive-lathe"} 0.0
machine_relay_state{display_name="esp32test",machine_name="esp32test"} 0.0
# HELP machine_oops_state The Oops state of the machine
# TYPE machine_oops_state gauge
machine_oops_state{display_name="Metal Mill",machine_name="metal-mill"} 0.0
machine_oops_state{display_name="hammer",machine_name="hammer"} 0.0
machine_oops_state{display_name="permissive-lathe",machine_name="permissive-lathe"} 0.0
machine_oops_state{display_name="restrictive-lathe",machine_name="restrictive-lathe"} 0.0
machine_oops_state{display_name="esp32test",machine_name="esp32test"} 0.0
# HELP machine_lockout_state The lockout state of the machine
# TYPE machine_lockout_state gauge
machine_lockout_state{display_name="Metal Mill",machine_name="metal-mill"} 0.0
machine_lockout_state{display_name="hammer",machine_name="hammer"} 0.0
machine_lockout_state{display_name="permissive-lathe",machine_name="permissive-lathe"} 0.0
machine_lockout_state{display_name="restrictive-lathe",machine_name="restrictive-lathe"} 0.0
machine_lockout_state{display_name="esp32test",machine_name="esp32test"} 0.0
# HELP machine_unauth_warn_only_state The unauthorized_warn_only state of the machine
# TYPE machine_unauth_warn_only_state gauge
machine_unauth_warn_only_state{display_name="Metal Mill",machine_name="metal-mill"} 0.0
machine_unauth_warn_only_state{display_name="hammer",machine_name="hammer"} 1.0
machine_unauth_warn_only_state{display_name="permissive-lathe",machine_name="permissive-lathe"} 1.0
machine_unauth_warn_only_state{display_name="restrictive-lathe",machine_name="restrictive-lathe"} 0.0
machine_unauth_warn_only_state{display_name="esp32test",machine_name="esp32test"} 1.0
# HELP machine_last_checkin_timestamp The last checkin timestamp for the machine
# TYPE machine_last_checkin_timestamp gauge
machine_last_checkin_timestamp{display_name="Metal Mill",machine_name="metal-mill"} 0.0
machine_last_checkin_timestamp{display_name="hammer",machine_name="hammer"} 0.0
machine_last_checkin_timestamp{display_name="permissive-lathe",machine_name="permissive-lathe"} 0.0
machine_last_checkin_timestamp{display_name="restrictive-lathe",machine_name="restrictive-lathe"} 0.0
machine_last_checkin_timestamp{display_name="esp32test",machine_name="esp32test"} 0.0
# HELP machine_last_update_timestamp The last update timestamp of the machine
# TYPE machine_last_update_timestamp gauge
machine_last_update_timestamp{display_name="Metal Mill",machine_name="metal-mill"} 0.0
machine_last_update_timestamp{display_name="hammer",machine_name="hammer"} 0.0
machine_last_update_timestamp{display_name="permissive-lathe",machine_name="permissive-lathe"} 0.0
machine_last_update_timestamp{display_name="restrictive-lathe",machine_name="restrictive-lathe"} 0.0
machine_last_update_timestamp{display_name="esp32test",machine_name="esp32test"} 0.0
# HELP machine_rfid_present Whether a RFID fob is present in the machine
# TYPE machine_rfid_present gauge
machine_rfid_present{display_name="Metal Mill",machine_name="metal-mill"} 0.0
machine_rfid_present{display_name="hammer",machine_name="hammer"} 0.0
machine_rfid_present{display_name="permissive-lathe",machine_name="permissive-lathe"} 0.0
machine_rfid_present{display_name="restrictive-lathe",machine_name="restrictive-lathe"} 0.0
machine_rfid_present{display_name="esp32test",machine_name="esp32test"} 0.0
# HELP machine_rfid_present_since_timestamp The timestamp since the RFID was inserter into the machine
# TYPE machine_rfid_present_since_timestamp gauge
machine_rfid_present_since_timestamp{display_name="Metal Mill",machine_name="metal-mill"} 0.0
machine_rfid_present_since_timestamp{display_name="hammer",machine_name="hammer"} 0.0
machine_rfid_present_since_timestamp{display_name="permissive-lathe",machine_name="permissive-lathe"} 0.0
machine_rfid_present_since_timestamp{display_name="restrictive-lathe",machine_name="restrictive-lathe"} 0.0
machine_rfid_present_since_timestamp{display_name="esp32test",machine_name="esp32test"} 0.0
# HELP machine_current_amps The amperage being used by the machine if applicable
# TYPE machine_current_amps gauge
machine_current_amps{display_name="Metal Mill",machine_name="metal-mill"} 0.0
machine_current_amps{display_name="hammer",machine_name="hammer"} 0.0
machine_current_amps{display_name="permissive-lathe",machine_name="permissive-lathe"} 0.0
machine_current_amps{display_name="restrictive-lathe",machine_name="restrictive-lathe"} 0.0
machine_current_amps{display_name="esp32test",machine_name="esp32test"} 0.0
# HELP machine_known_user Whether a known user RFID is inserted into the machine
# TYPE machine_known_user gauge
machine_known_user{display_name="Metal Mill",machine_name="metal-mill"} 0.0
machine_known_user{display_name="hammer",machine_name="hammer"} 0.0
machine_known_user{display_name="permissive-lathe",machine_name="permissive-lathe"} 0.0
machine_known_user{display_name="restrictive-lathe",machine_name="restrictive-lathe"} 0.0
machine_known_user{display_name="esp32test",machine_name="esp32test"} 0.0
# HELP machine_uptime_seconds The machine uptime seconds
# TYPE machine_uptime_seconds gauge
machine_uptime_seconds{display_name="Metal Mill",machine_name="metal-mill"} 0.0
machine_uptime_seconds{display_name="hammer",machine_name="hammer"} 0.0
machine_uptime_seconds{display_name="permissive-lathe",machine_name="permissive-lathe"} 0.0
machine_uptime_seconds{display_name="restrictive-lathe",machine_name="restrictive-lathe"} 0.0
machine_uptime_seconds{display_name="esp32test",machine_name="esp32test"} 0.0
# HELP machine_wifi_signal_db The machine WiFi signal in dB
# TYPE machine_wifi_signal_db gauge
machine_wifi_signal_db{display_name="Metal Mill",machine_name="metal-mill"} 0.0
machine_wifi_signal_db{display_name="hammer",machine_name="hammer"} 0.0
machine_wifi_signal_db{display_name="permissive-lathe",machine_name="permissive-lathe"} 0.0
machine_wifi_signal_db{display_name="restrictive-lathe",machine_name="restrictive-lathe"} 0.0
machine_wifi_signal_db{display_name="esp32test",machine_name="esp32test"} 0.0
# HELP machine_wifi_signal_percent The machine WiFi signal in percent
# TYPE machine_wifi_signal_percent gauge
machine_wifi_signal_percent{display_name="Metal Mill",machine_name="metal-mill"} 0.0
machine_wifi_signal_percent{display_name="hammer",machine_name="hammer"} 0.0
machine_wifi_signal_percent{display_name="permissive-lathe",machine_name="permissive-lathe"} 0.0
machine_wifi_signal_percent{display_name="restrictive-lathe",machine_name="restrictive-lathe"} 0.0
machine_wifi_signal_percent{display_name="esp32test",machine_name="esp32test"} 0.0
# HELP machine_esp_temperature_c The machine ESP32 internal temperature in °C
# TYPE machine_esp_temperature_c gauge
machine_esp_temperature_c{display_name="Metal Mill",machine_name="metal-mill"} 0.0
machine_esp_temperature_c{display_name="hammer",machine_name="hammer"} 0.0
machine_esp_temperature_c{display_name="permissive-lathe",machine_name="permissive-lathe"} 0.0
machine_esp_temperature_c{display_name="restrictive-lathe",machine_name="restrictive-lathe"} 0.0
machine_esp_temperature_c{display_name="esp32test",machine_name="esp32test"} 0.0
# HELP machine_status_led The machine status LED state
# TYPE machine_status_led gauge
machine_status_led{display_name="Metal Mill",led_attribute="red",machine_name="metal-mill"} 0.0
machine_status_led{display_name="Metal Mill",led_attribute="green",machine_name="metal-mill"} 0.0
machine_status_led{display_name="Metal Mill",led_attribute="blue",machine_name="metal-mill"} 0.0
machine_status_led{display_name="Metal Mill",led_attribute="brightness",machine_name="metal-mill"} 0.0
machine_status_led{display_name="hammer",led_attribute="red",machine_name="hammer"} 0.0
machine_status_led{display_name="hammer",led_attribute="green",machine_name="hammer"} 0.0
machine_status_led{display_name="hammer",led_attribute="blue",machine_name="hammer"} 0.0
machine_status_led{display_name="hammer",led_attribute="brightness",machine_name="hammer"} 0.0
machine_status_led{display_name="permissive-lathe",led_attribute="red",machine_name="permissive-lathe"} 0.0
machine_status_led{display_name="permissive-lathe",led_attribute="green",machine_name="permissive-lathe"} 0.0
machine_status_led{display_name="permissive-lathe",led_attribute="blue",machine_name="permissive-lathe"} 0.0
machine_status_led{display_name="permissive-lathe",led_attribute="brightness",machine_name="permissive-lathe"} 0.0
machine_status_led{display_name="restrictive-lathe",led_attribute="red",machine_name="restrictive-lathe"} 0.0
machine_status_led{display_name="restrictive-lathe",led_attribute="green",machine_name="restrictive-lathe"} 0.0
machine_status_led{display_name="restrictive-lathe",led_attribute="blue",machine_name="restrictive-lathe"} 0.0
machine_status_led{display_name="restrictive-lathe",led_attribute="brightness",machine_name="restrictive-lathe"} 0.0
machine_status_led{display_name="esp32test",led_attribute="red",machine_name="esp32test"} 0.0
machine_status_led{display_name="esp32test",led_attribute="green",machine_name="esp32test"} 0.0
machine_status_led{display_name="esp32test",led_attribute="blue",machine_name="esp32test"} 0.0
machine_status_led{display_name="esp32test",led_attribute="brightness",machine_name="esp32test"} 0.0

Grafana Dashboard

A pre-built Grafana dashboard is provided to visualize the metrics exposed by the Prometheus endpoint. The dashboard provides comprehensive monitoring and visualization of the machine access control system.

Dashboard Features

The Grafana dashboard includes the following visualizations:

System Status

  • Server uptime tracking

  • User and RFID fob counts with historical trends

  • Machine connectivity monitoring (5-minute check-in status)

  • Machine lockout status overview

Machine Usage Overview

  • Real-time relay state visualization (which machines are powered on)

  • RFID presence indicators

  • Oops button status monitoring

  • Machine relay state timeline

Machine Health & Connectivity

  • WiFi signal strength monitoring (both percentage and dB)

  • ESP32 internal temperature tracking

  • Machine controller uptime

Usage Analytics

  • Current session duration tracking

  • 24-hour usage distribution by machine

  • Known user presence indicators

Machine Details

  • Per-machine drill-down view with detailed metrics

  • Selectable via dashboard variable dropdown

Importing the Dashboard

To import the dashboard into Grafana:

  1. In Grafana, navigate to DashboardsImport

  2. Click Upload JSON file and select the dashboard JSON file

  3. Select your Prometheus datasource when prompted

  4. Click Import

The dashboard is configured with:

  • 5-second auto-refresh rate (adjustable)

  • 24-hour default time range

  • Machine selector variable for detailed views

Dashboard JSON

The complete Grafana dashboard JSON is available below:

   1{
   2  "annotations": {
   3    "list": [
   4      {
   5        "builtIn": 1,
   6        "datasource": {
   7          "type": "datasource",
   8          "uid": "grafana"
   9        },
  10        "enable": true,
  11        "hide": true,
  12        "iconColor": "rgba(0, 211, 255, 1)",
  13        "name": "Annotations & Alerts",
  14        "type": "dashboard"
  15      }
  16    ]
  17  },
  18  "editable": true,
  19  "fiscalYearStartMonth": 0,
  20  "graphTooltip": 0,
  21  "id": null,
  22  "links": [],
  23  "panels": [
  24    {
  25      "datasource": {
  26        "type": "prometheus",
  27        "uid": "${DS_PROMETHEUS}"
  28      },
  29      "fieldConfig": {
  30        "defaults": {
  31          "color": {
  32            "mode": "thresholds"
  33          },
  34          "mappings": [],
  35          "thresholds": {
  36            "mode": "absolute",
  37            "steps": [
  38              {
  39                "color": "green",
  40                "value": null
  41              }
  42            ]
  43          },
  44          "unit": "dateTimeFromNow"
  45        },
  46        "overrides": []
  47      },
  48      "gridPos": {
  49        "h": 4,
  50        "w": 6,
  51        "x": 0,
  52        "y": 0
  53      },
  54      "id": 1,
  55      "options": {
  56        "colorMode": "value",
  57        "graphMode": "none",
  58        "justifyMode": "auto",
  59        "orientation": "auto",
  60        "reduceOptions": {
  61          "values": false,
  62          "calcs": [
  63            "lastNotNull"
  64          ],
  65          "fields": ""
  66        },
  67        "showPercentChange": false,
  68        "textMode": "auto",
  69        "wideLayout": true
  70      },
  71      "pluginVersion": "11.0.0",
  72      "targets": [
  73        {
  74          "expr": "app_start_timestamp * 1000",
  75          "refId": "A"
  76        }
  77      ],
  78      "title": "Server Uptime",
  79      "type": "stat"
  80    },
  81    {
  82      "datasource": {
  83        "type": "prometheus",
  84        "uid": "${DS_PROMETHEUS}"
  85      },
  86      "fieldConfig": {
  87        "defaults": {
  88          "color": {
  89            "mode": "thresholds"
  90          },
  91          "mappings": [],
  92          "thresholds": {
  93            "mode": "absolute",
  94            "steps": [
  95              {
  96                "color": "green",
  97                "value": null
  98              }
  99            ]
 100          }
 101        },
 102        "overrides": []
 103      },
 104      "gridPos": {
 105        "h": 4,
 106        "w": 3,
 107        "x": 6,
 108        "y": 0
 109      },
 110      "id": 2,
 111      "options": {
 112        "colorMode": "value",
 113        "graphMode": "area",
 114        "justifyMode": "auto",
 115        "orientation": "auto",
 116        "reduceOptions": {
 117          "values": false,
 118          "calcs": [
 119            "lastNotNull"
 120          ],
 121          "fields": ""
 122        },
 123        "showPercentChange": false,
 124        "textMode": "auto",
 125        "wideLayout": true
 126      },
 127      "pluginVersion": "11.0.0",
 128      "targets": [
 129        {
 130          "expr": "user_count",
 131          "refId": "A"
 132        }
 133      ],
 134      "title": "Users",
 135      "type": "stat"
 136    },
 137    {
 138      "datasource": {
 139        "type": "prometheus",
 140        "uid": "${DS_PROMETHEUS}"
 141      },
 142      "fieldConfig": {
 143        "defaults": {
 144          "color": {
 145            "mode": "thresholds"
 146          },
 147          "mappings": [],
 148          "thresholds": {
 149            "mode": "absolute",
 150            "steps": [
 151              {
 152                "color": "green",
 153                "value": null
 154              }
 155            ]
 156          }
 157        },
 158        "overrides": []
 159      },
 160      "gridPos": {
 161        "h": 4,
 162        "w": 3,
 163        "x": 9,
 164        "y": 0
 165      },
 166      "id": 3,
 167      "options": {
 168        "colorMode": "value",
 169        "graphMode": "area",
 170        "justifyMode": "auto",
 171        "orientation": "auto",
 172        "reduceOptions": {
 173          "values": false,
 174          "calcs": [
 175            "lastNotNull"
 176          ],
 177          "fields": ""
 178        },
 179        "showPercentChange": false,
 180        "textMode": "auto",
 181        "wideLayout": true
 182      },
 183      "pluginVersion": "11.0.0",
 184      "targets": [
 185        {
 186          "expr": "fob_count",
 187          "refId": "A"
 188        }
 189      ],
 190      "title": "RFID Fobs",
 191      "type": "stat"
 192    },
 193    {
 194      "datasource": {
 195        "type": "prometheus",
 196        "uid": "${DS_PROMETHEUS}"
 197      },
 198      "fieldConfig": {
 199        "defaults": {
 200          "color": {
 201            "mode": "thresholds"
 202          },
 203          "mappings": [
 204            {
 205              "options": {
 206                "0": {
 207                  "color": "red",
 208                  "text": "Offline"
 209                }
 210              },
 211              "type": "value"
 212            },
 213            {
 214              "options": {
 215                "from": 1,
 216                "result": {
 217                  "color": "green",
 218                  "text": "Online"
 219                },
 220                "to": 999999999999
 221              },
 222              "type": "range"
 223            }
 224          ],
 225          "thresholds": {
 226            "mode": "absolute",
 227            "steps": [
 228              {
 229                "color": "red",
 230                "value": null
 231              },
 232              {
 233                "color": "green",
 234                "value": 1
 235              }
 236            ]
 237          }
 238        },
 239        "overrides": []
 240      },
 241      "gridPos": {
 242        "h": 4,
 243        "w": 6,
 244        "x": 12,
 245        "y": 0
 246      },
 247      "id": 4,
 248      "options": {
 249        "colorMode": "background",
 250        "graphMode": "none",
 251        "justifyMode": "auto",
 252        "orientation": "auto",
 253        "reduceOptions": {
 254          "values": false,
 255          "calcs": [
 256            "lastNotNull"
 257          ],
 258          "fields": ""
 259        },
 260        "showPercentChange": false,
 261        "textMode": "name",
 262        "wideLayout": true
 263      },
 264      "pluginVersion": "11.0.0",
 265      "targets": [
 266        {
 267          "expr": "machine_last_checkin_timestamp > (time() - 300)",
 268          "legendFormat": "{{display_name}}",
 269          "refId": "A"
 270        }
 271      ],
 272      "title": "Machine Connectivity (5min)",
 273      "type": "stat"
 274    },
 275    {
 276      "datasource": {
 277        "type": "prometheus",
 278        "uid": "${DS_PROMETHEUS}"
 279      },
 280      "fieldConfig": {
 281        "defaults": {
 282          "color": {
 283            "mode": "thresholds"
 284          },
 285          "mappings": [
 286            {
 287              "options": {
 288                "0": {
 289                  "color": "green",
 290                  "text": "Available"
 291                },
 292                "1": {
 293                  "color": "red",
 294                  "text": "LOCKED OUT"
 295                }
 296              },
 297              "type": "value"
 298            }
 299          ],
 300          "thresholds": {
 301            "mode": "absolute",
 302            "steps": [
 303              {
 304                "color": "green",
 305                "value": null
 306              },
 307              {
 308                "color": "red",
 309                "value": 1
 310              }
 311            ]
 312          }
 313        },
 314        "overrides": []
 315      },
 316      "gridPos": {
 317        "h": 4,
 318        "w": 6,
 319        "x": 18,
 320        "y": 0
 321      },
 322      "id": 5,
 323      "options": {
 324        "colorMode": "background",
 325        "graphMode": "none",
 326        "justifyMode": "auto",
 327        "orientation": "auto",
 328        "reduceOptions": {
 329          "values": false,
 330          "calcs": [
 331            "lastNotNull"
 332          ],
 333          "fields": ""
 334        },
 335        "showPercentChange": false,
 336        "textMode": "name",
 337        "wideLayout": true
 338      },
 339      "pluginVersion": "11.0.0",
 340      "targets": [
 341        {
 342          "expr": "machine_lockout_state",
 343          "legendFormat": "{{display_name}}",
 344          "refId": "A"
 345        }
 346      ],
 347      "title": "Machine Lockout Status",
 348      "type": "stat"
 349    },
 350    {
 351      "collapsed": false,
 352      "gridPos": {
 353        "h": 1,
 354        "w": 24,
 355        "x": 0,
 356        "y": 4
 357      },
 358      "id": 20,
 359      "panels": [],
 360      "title": "Machine Usage Overview",
 361      "type": "row"
 362    },
 363    {
 364      "datasource": {
 365        "type": "prometheus",
 366        "uid": "${DS_PROMETHEUS}"
 367      },
 368      "fieldConfig": {
 369        "defaults": {
 370          "color": {
 371            "mode": "thresholds"
 372          },
 373          "mappings": [
 374            {
 375              "options": {
 376                "0": {
 377                  "color": "semi-dark-blue",
 378                  "text": "Idle"
 379                },
 380                "1": {
 381                  "color": "green",
 382                  "text": "IN USE"
 383                }
 384              },
 385              "type": "value"
 386            }
 387          ],
 388          "thresholds": {
 389            "mode": "absolute",
 390            "steps": [
 391              {
 392                "color": "blue",
 393                "value": null
 394              },
 395              {
 396                "color": "green",
 397                "value": 1
 398              }
 399            ]
 400          }
 401        },
 402        "overrides": []
 403      },
 404      "gridPos": {
 405        "h": 6,
 406        "w": 8,
 407        "x": 0,
 408        "y": 5
 409      },
 410      "id": 6,
 411      "options": {
 412        "colorMode": "background",
 413        "graphMode": "none",
 414        "justifyMode": "auto",
 415        "orientation": "auto",
 416        "reduceOptions": {
 417          "values": false,
 418          "calcs": [
 419            "lastNotNull"
 420          ],
 421          "fields": ""
 422        },
 423        "showPercentChange": false,
 424        "textMode": "name",
 425        "wideLayout": true
 426      },
 427      "pluginVersion": "11.0.0",
 428      "targets": [
 429        {
 430          "expr": "machine_relay_state",
 431          "legendFormat": "{{display_name}}",
 432          "refId": "A"
 433        }
 434      ],
 435      "title": "Machine Relay Status",
 436      "type": "stat"
 437    },
 438    {
 439      "datasource": {
 440        "type": "prometheus",
 441        "uid": "${DS_PROMETHEUS}"
 442      },
 443      "fieldConfig": {
 444        "defaults": {
 445          "color": {
 446            "mode": "thresholds"
 447          },
 448          "mappings": [
 449            {
 450              "options": {
 451                "0": {
 452                  "color": "semi-dark-blue",
 453                  "text": "No RFID"
 454                },
 455                "1": {
 456                  "color": "green",
 457                  "text": "RFID Present"
 458                }
 459              },
 460              "type": "value"
 461            }
 462          ],
 463          "thresholds": {
 464            "mode": "absolute",
 465            "steps": [
 466              {
 467                "color": "blue",
 468                "value": null
 469              },
 470              {
 471                "color": "green",
 472                "value": 1
 473              }
 474            ]
 475          }
 476        },
 477        "overrides": []
 478      },
 479      "gridPos": {
 480        "h": 6,
 481        "w": 8,
 482        "x": 8,
 483        "y": 5
 484      },
 485      "id": 7,
 486      "options": {
 487        "colorMode": "background",
 488        "graphMode": "none",
 489        "justifyMode": "auto",
 490        "orientation": "auto",
 491        "reduceOptions": {
 492          "values": false,
 493          "calcs": [
 494            "lastNotNull"
 495          ],
 496          "fields": ""
 497        },
 498        "showPercentChange": false,
 499        "textMode": "name",
 500        "wideLayout": true
 501      },
 502      "pluginVersion": "11.0.0",
 503      "targets": [
 504        {
 505          "expr": "machine_rfid_present",
 506          "legendFormat": "{{display_name}}",
 507          "refId": "A"
 508        }
 509      ],
 510      "title": "RFID Presence",
 511      "type": "stat"
 512    },
 513    {
 514      "datasource": {
 515        "type": "prometheus",
 516        "uid": "${DS_PROMETHEUS}"
 517      },
 518      "fieldConfig": {
 519        "defaults": {
 520          "color": {
 521            "mode": "thresholds"
 522          },
 523          "mappings": [
 524            {
 525              "options": {
 526                "0": {
 527                  "color": "red",
 528                  "text": "OOPS!"
 529                },
 530                "1": {
 531                  "color": "dark-gray",
 532                  "text": "OK"
 533                }
 534              },
 535              "type": "value"
 536            }
 537          ],
 538          "thresholds": {
 539            "mode": "absolute",
 540            "steps": [
 541              {
 542                "color": "dark-gray",
 543                "value": null
 544              },
 545              {
 546                "color": "red",
 547                "value": 0
 548              },
 549              {
 550                "color": "dark-gray",
 551                "value": 1
 552              }
 553            ]
 554          }
 555        },
 556        "overrides": []
 557      },
 558      "gridPos": {
 559        "h": 6,
 560        "w": 8,
 561        "x": 16,
 562        "y": 5
 563      },
 564      "id": 8,
 565      "options": {
 566        "colorMode": "background",
 567        "graphMode": "none",
 568        "justifyMode": "auto",
 569        "orientation": "auto",
 570        "reduceOptions": {
 571          "values": false,
 572          "calcs": [
 573            "lastNotNull"
 574          ],
 575          "fields": ""
 576        },
 577        "showPercentChange": false,
 578        "textMode": "name",
 579        "wideLayout": true
 580      },
 581      "pluginVersion": "11.0.0",
 582      "targets": [
 583        {
 584          "expr": "machine_oops_state == 0",
 585          "legendFormat": "{{display_name}}",
 586          "refId": "A"
 587        }
 588      ],
 589      "title": "Machine Status (Oops Button)",
 590      "type": "stat"
 591    },
 592    {
 593      "datasource": {
 594        "type": "prometheus",
 595        "uid": "${DS_PROMETHEUS}"
 596      },
 597      "fieldConfig": {
 598        "defaults": {
 599          "color": {
 600            "mode": "palette-classic"
 601          },
 602          "custom": {
 603            "axisBorderShow": false,
 604            "axisCenteredZero": false,
 605            "axisColorMode": "text",
 606            "axisLabel": "",
 607            "axisPlacement": "auto",
 608            "barAlignment": 0,
 609            "drawStyle": "line",
 610            "fillOpacity": 10,
 611            "gradientMode": "none",
 612            "hideFrom": {
 613              "tooltip": false,
 614              "viz": false,
 615              "legend": false
 616            },
 617            "insertNulls": false,
 618            "lineInterpolation": "stepAfter",
 619            "lineWidth": 2,
 620            "pointSize": 5,
 621            "scaleDistribution": {
 622              "type": "linear"
 623            },
 624            "showPoints": "never",
 625            "spanNulls": false,
 626            "stacking": {
 627              "group": "A",
 628              "mode": "none"
 629            },
 630            "thresholdsStyle": {
 631              "mode": "off"
 632            }
 633          },
 634          "mappings": [],
 635          "max": 1,
 636          "min": 0,
 637          "thresholds": {
 638            "mode": "absolute",
 639            "steps": [
 640              {
 641                "color": "green",
 642                "value": null
 643              }
 644            ]
 645          },
 646          "unit": "short"
 647        },
 648        "overrides": []
 649      },
 650      "gridPos": {
 651        "h": 8,
 652        "w": 12,
 653        "x": 0,
 654        "y": 11
 655      },
 656      "id": 9,
 657      "options": {
 658        "legend": {
 659          "calcs": [],
 660          "displayMode": "list",
 661          "placement": "bottom",
 662          "showLegend": true
 663        },
 664        "tooltip": {
 665          "mode": "multi",
 666          "sort": "none"
 667        }
 668      },
 669      "pluginVersion": "11.0.0",
 670      "targets": [
 671        {
 672          "expr": "machine_relay_state",
 673          "legendFormat": "{{display_name}}",
 674          "refId": "A"
 675        }
 676      ],
 677      "title": "Machine Relay State Over Time",
 678      "type": "timeseries"
 679    },
 680    {
 681      "datasource": {
 682        "type": "prometheus",
 683        "uid": "${DS_PROMETHEUS}"
 684      },
 685      "fieldConfig": {
 686        "defaults": {
 687          "color": {
 688            "mode": "palette-classic"
 689          },
 690          "custom": {
 691            "axisBorderShow": false,
 692            "axisCenteredZero": false,
 693            "axisColorMode": "text",
 694            "axisLabel": "",
 695            "axisPlacement": "auto",
 696            "barAlignment": 0,
 697            "drawStyle": "line",
 698            "fillOpacity": 10,
 699            "gradientMode": "none",
 700            "hideFrom": {
 701              "tooltip": false,
 702              "viz": false,
 703              "legend": false
 704            },
 705            "insertNulls": false,
 706            "lineInterpolation": "linear",
 707            "lineWidth": 1,
 708            "pointSize": 5,
 709            "scaleDistribution": {
 710              "type": "log",
 711              "log": 10
 712            },
 713            "showPoints": "never",
 714            "spanNulls": false,
 715            "stacking": {
 716              "group": "A",
 717              "mode": "none"
 718            },
 719            "thresholdsStyle": {
 720              "mode": "off"
 721            }
 722          },
 723          "mappings": [],
 724          "thresholds": {
 725            "mode": "absolute",
 726            "steps": [
 727              {
 728                "color": "green",
 729                "value": null
 730              },
 731              {
 732                "color": "yellow",
 733                "value": 60
 734              },
 735              {
 736                "color": "orange",
 737                "value": 300
 738              },
 739              {
 740                "color": "red",
 741                "value": 600
 742              }
 743            ]
 744          },
 745          "unit": "s"
 746        },
 747        "overrides": []
 748      },
 749      "gridPos": {
 750        "h": 8,
 751        "w": 12,
 752        "x": 12,
 753        "y": 11
 754      },
 755      "id": 10,
 756      "options": {
 757        "legend": {
 758          "calcs": [
 759            "lastNotNull"
 760          ],
 761          "displayMode": "table",
 762          "placement": "bottom",
 763          "showLegend": true
 764        },
 765        "tooltip": {
 766          "mode": "multi",
 767          "sort": "none"
 768        }
 769      },
 770      "pluginVersion": "11.0.0",
 771      "targets": [
 772        {
 773          "expr": "time() - machine_last_checkin_timestamp",
 774          "legendFormat": "{{display_name}}",
 775          "refId": "A"
 776        }
 777      ],
 778      "title": "Time Since Last Check-In (Log Scale)",
 779      "type": "timeseries"
 780    },
 781    {
 782      "collapsed": false,
 783      "gridPos": {
 784        "h": 1,
 785        "w": 24,
 786        "x": 0,
 787        "y": 19
 788      },
 789      "id": 21,
 790      "panels": [],
 791      "title": "Machine Health & Connectivity",
 792      "type": "row"
 793    },
 794    {
 795      "datasource": {
 796        "type": "prometheus",
 797        "uid": "${DS_PROMETHEUS}"
 798      },
 799      "fieldConfig": {
 800        "defaults": {
 801          "color": {
 802            "mode": "palette-classic"
 803          },
 804          "custom": {
 805            "axisBorderShow": false,
 806            "axisCenteredZero": false,
 807            "axisColorMode": "text",
 808            "axisLabel": "",
 809            "axisPlacement": "auto",
 810            "barAlignment": 0,
 811            "drawStyle": "line",
 812            "fillOpacity": 10,
 813            "gradientMode": "none",
 814            "hideFrom": {
 815              "tooltip": false,
 816              "viz": false,
 817              "legend": false
 818            },
 819            "insertNulls": false,
 820            "lineInterpolation": "linear",
 821            "lineWidth": 1,
 822            "pointSize": 5,
 823            "scaleDistribution": {
 824              "type": "linear"
 825            },
 826            "showPoints": "never",
 827            "spanNulls": false,
 828            "stacking": {
 829              "group": "A",
 830              "mode": "none"
 831            },
 832            "thresholdsStyle": {
 833              "mode": "off"
 834            }
 835          },
 836          "mappings": [],
 837          "thresholds": {
 838            "mode": "absolute",
 839            "steps": [
 840              {
 841                "color": "green",
 842                "value": null
 843              },
 844              {
 845                "color": "red",
 846                "value": 80
 847              }
 848            ]
 849          },
 850          "unit": "percent"
 851        },
 852        "overrides": []
 853      },
 854      "gridPos": {
 855        "h": 8,
 856        "w": 12,
 857        "x": 0,
 858        "y": 20
 859      },
 860      "id": 11,
 861      "options": {
 862        "legend": {
 863          "calcs": [
 864            "mean",
 865            "min"
 866          ],
 867          "displayMode": "table",
 868          "placement": "bottom",
 869          "showLegend": true
 870        },
 871        "tooltip": {
 872          "mode": "multi",
 873          "sort": "none"
 874        }
 875      },
 876      "pluginVersion": "11.0.0",
 877      "targets": [
 878        {
 879          "expr": "machine_wifi_signal_percent",
 880          "legendFormat": "{{display_name}}",
 881          "refId": "A"
 882        }
 883      ],
 884      "title": "WiFi Signal Strength (%)",
 885      "type": "timeseries"
 886    },
 887    {
 888      "datasource": {
 889        "type": "prometheus",
 890        "uid": "${DS_PROMETHEUS}"
 891      },
 892      "fieldConfig": {
 893        "defaults": {
 894          "color": {
 895            "mode": "palette-classic"
 896          },
 897          "custom": {
 898            "axisBorderShow": false,
 899            "axisCenteredZero": false,
 900            "axisColorMode": "text",
 901            "axisLabel": "",
 902            "axisPlacement": "auto",
 903            "barAlignment": 0,
 904            "drawStyle": "line",
 905            "fillOpacity": 10,
 906            "gradientMode": "none",
 907            "hideFrom": {
 908              "tooltip": false,
 909              "viz": false,
 910              "legend": false
 911            },
 912            "insertNulls": false,
 913            "lineInterpolation": "linear",
 914            "lineWidth": 1,
 915            "pointSize": 5,
 916            "scaleDistribution": {
 917              "type": "linear"
 918            },
 919            "showPoints": "never",
 920            "spanNulls": false,
 921            "stacking": {
 922              "group": "A",
 923              "mode": "none"
 924            },
 925            "thresholdsStyle": {
 926              "mode": "off"
 927            }
 928          },
 929          "mappings": [],
 930          "thresholds": {
 931            "mode": "absolute",
 932            "steps": [
 933              {
 934                "color": "green",
 935                "value": null
 936              },
 937              {
 938                "color": "red",
 939                "value": 80
 940              }
 941            ]
 942          },
 943          "unit": "celsius"
 944        },
 945        "overrides": []
 946      },
 947      "gridPos": {
 948        "h": 8,
 949        "w": 12,
 950        "x": 0,
 951        "y": 28
 952      },
 953      "id": 12,
 954      "options": {
 955        "legend": {
 956          "calcs": [
 957            "mean",
 958            "max"
 959          ],
 960          "displayMode": "table",
 961          "placement": "bottom",
 962          "showLegend": true
 963        },
 964        "tooltip": {
 965          "mode": "multi",
 966          "sort": "none"
 967        }
 968      },
 969      "pluginVersion": "11.0.0",
 970      "targets": [
 971        {
 972          "expr": "machine_esp_temperature_c",
 973          "legendFormat": "{{display_name}}",
 974          "refId": "A"
 975        }
 976      ],
 977      "title": "ESP32 Temperature",
 978      "type": "timeseries"
 979    },
 980    {
 981      "datasource": {
 982        "type": "prometheus",
 983        "uid": "${DS_PROMETHEUS}"
 984      },
 985      "fieldConfig": {
 986        "defaults": {
 987          "color": {
 988            "mode": "palette-classic"
 989          },
 990          "custom": {
 991            "axisBorderShow": false,
 992            "axisCenteredZero": false,
 993            "axisColorMode": "text",
 994            "axisLabel": "",
 995            "axisPlacement": "auto",
 996            "barAlignment": 0,
 997            "drawStyle": "line",
 998            "fillOpacity": 10,
 999            "gradientMode": "none",
1000            "hideFrom": {
1001              "tooltip": false,
1002              "viz": false,
1003              "legend": false
1004            },
1005            "insertNulls": false,
1006            "lineInterpolation": "linear",
1007            "lineWidth": 1,
1008            "pointSize": 5,
1009            "scaleDistribution": {
1010              "type": "log",
1011              "log": 10
1012            },
1013            "showPoints": "never",
1014            "spanNulls": false,
1015            "stacking": {
1016              "group": "A",
1017              "mode": "none"
1018            },
1019            "thresholdsStyle": {
1020              "mode": "off"
1021            }
1022          },
1023          "mappings": [],
1024          "thresholds": {
1025            "mode": "absolute",
1026            "steps": [
1027              {
1028                "color": "green",
1029                "value": null
1030              }
1031            ]
1032          },
1033          "unit": "s"
1034        },
1035        "overrides": []
1036      },
1037      "gridPos": {
1038        "h": 8,
1039        "w": 12,
1040        "x": 12,
1041        "y": 28
1042      },
1043      "id": 13,
1044      "options": {
1045        "legend": {
1046          "calcs": [
1047            "lastNotNull"
1048          ],
1049          "displayMode": "table",
1050          "placement": "bottom",
1051          "showLegend": true
1052        },
1053        "tooltip": {
1054          "mode": "multi",
1055          "sort": "none"
1056        }
1057      },
1058      "pluginVersion": "11.0.0",
1059      "targets": [
1060        {
1061          "expr": "machine_uptime_seconds",
1062          "legendFormat": "{{display_name}}",
1063          "refId": "A"
1064        }
1065      ],
1066      "title": "Machine Controller Uptime (Log Scale)",
1067      "type": "timeseries"
1068    },
1069    {
1070      "datasource": {
1071        "type": "prometheus",
1072        "uid": "${DS_PROMETHEUS}"
1073      },
1074      "fieldConfig": {
1075        "defaults": {
1076          "color": {
1077            "mode": "palette-classic"
1078          },
1079          "custom": {
1080            "axisBorderShow": false,
1081            "axisCenteredZero": false,
1082            "axisColorMode": "text",
1083            "axisLabel": "",
1084            "axisPlacement": "auto",
1085            "barAlignment": 0,
1086            "drawStyle": "line",
1087            "fillOpacity": 10,
1088            "gradientMode": "none",
1089            "hideFrom": {
1090              "tooltip": false,
1091              "viz": false,
1092              "legend": false
1093            },
1094            "insertNulls": false,
1095            "lineInterpolation": "linear",
1096            "lineWidth": 1,
1097            "pointSize": 5,
1098            "scaleDistribution": {
1099              "type": "linear"
1100            },
1101            "showPoints": "never",
1102            "spanNulls": false,
1103            "stacking": {
1104              "group": "A",
1105              "mode": "none"
1106            },
1107            "thresholdsStyle": {
1108              "mode": "off"
1109            }
1110          },
1111          "mappings": [],
1112          "thresholds": {
1113            "mode": "absolute",
1114            "steps": [
1115              {
1116                "color": "green",
1117                "value": null
1118              }
1119            ]
1120          },
1121          "unit": "dB"
1122        },
1123        "overrides": []
1124      },
1125      "gridPos": {
1126        "h": 8,
1127        "w": 12,
1128        "x": 12,
1129        "y": 20
1130      },
1131      "id": 14,
1132      "options": {
1133        "legend": {
1134          "calcs": [
1135            "mean",
1136            "min"
1137          ],
1138          "displayMode": "table",
1139          "placement": "bottom",
1140          "showLegend": true
1141        },
1142        "tooltip": {
1143          "mode": "multi",
1144          "sort": "none"
1145        }
1146      },
1147      "pluginVersion": "11.0.0",
1148      "targets": [
1149        {
1150          "expr": "machine_wifi_signal_db",
1151          "legendFormat": "{{display_name}}",
1152          "refId": "A"
1153        }
1154      ],
1155      "title": "WiFi Signal Strength (dB)",
1156      "type": "timeseries"
1157    },
1158    {
1159      "collapsed": false,
1160      "gridPos": {
1161        "h": 1,
1162        "w": 24,
1163        "x": 0,
1164        "y": 36
1165      },
1166      "id": 22,
1167      "panels": [],
1168      "title": "Usage Analytics",
1169      "type": "row"
1170    },
1171    {
1172      "datasource": {
1173        "type": "prometheus",
1174        "uid": "${DS_PROMETHEUS}"
1175      },
1176      "fieldConfig": {
1177        "defaults": {
1178          "color": {
1179            "mode": "thresholds"
1180          },
1181          "mappings": [],
1182          "thresholds": {
1183            "mode": "absolute",
1184            "steps": [
1185              {
1186                "color": "green",
1187                "value": null
1188              }
1189            ]
1190          },
1191          "unit": "dtdurations"
1192        },
1193        "overrides": []
1194      },
1195      "gridPos": {
1196        "h": 8,
1197        "w": 12,
1198        "x": 0,
1199        "y": 37
1200      },
1201      "id": 15,
1202      "options": {
1203        "displayMode": "gradient",
1204        "maxVizHeight": 300,
1205        "minVizHeight": 16,
1206        "minVizWidth": 8,
1207        "namePlacement": "auto",
1208        "orientation": "horizontal",
1209        "reduceOptions": {
1210          "values": false,
1211          "calcs": [
1212            "lastNotNull"
1213          ],
1214          "fields": ""
1215        },
1216        "showUnfilled": true,
1217        "sizing": "auto",
1218        "valueMode": "color"
1219      },
1220      "pluginVersion": "11.0.0",
1221      "targets": [
1222        {
1223          "expr": "(time() - machine_rfid_present_since_timestamp) * on() (machine_rfid_present > 0)",
1224          "legendFormat": "{{display_name}}",
1225          "refId": "A"
1226        }
1227      ],
1228      "title": "Current Session Duration",
1229      "type": "bargauge"
1230    },
1231    {
1232      "datasource": {
1233        "type": "prometheus",
1234        "uid": "${DS_PROMETHEUS}"
1235      },
1236      "fieldConfig": {
1237        "defaults": {
1238          "color": {
1239            "mode": "palette-classic"
1240          },
1241          "custom": {
1242            "hideFrom": {
1243              "tooltip": false,
1244              "viz": false,
1245              "legend": false
1246            }
1247          },
1248          "mappings": []
1249        },
1250        "overrides": []
1251      },
1252      "gridPos": {
1253        "h": 8,
1254        "w": 6,
1255        "x": 12,
1256        "y": 37
1257      },
1258      "id": 16,
1259      "options": {
1260        "legend": {
1261          "displayMode": "table",
1262          "placement": "right",
1263          "showLegend": true,
1264          "values": [
1265            "value"
1266          ]
1267        },
1268        "pieType": "donut",
1269        "tooltip": {
1270          "mode": "single",
1271          "sort": "none"
1272        }
1273      },
1274      "pluginVersion": "11.0.0",
1275      "targets": [
1276        {
1277          "expr": "sum(increase(machine_relay_state[24h])) by (machine_name)",
1278          "legendFormat": "{{display_name}}",
1279          "refId": "A"
1280        }
1281      ],
1282      "title": "Machine Usage (24h)",
1283      "type": "piechart"
1284    },
1285    {
1286      "datasource": {
1287        "type": "prometheus",
1288        "uid": "${DS_PROMETHEUS}"
1289      },
1290      "fieldConfig": {
1291        "defaults": {
1292          "color": {
1293            "mode": "thresholds"
1294          },
1295          "mappings": [
1296            {
1297              "options": {
1298                "0": {
1299                  "text": "No"
1300                },
1301                "1": {
1302                  "text": "Yes"
1303                }
1304              },
1305              "type": "value"
1306            }
1307          ],
1308          "thresholds": {
1309            "mode": "absolute",
1310            "steps": [
1311              {
1312                "color": "green",
1313                "value": null
1314              }
1315            ]
1316          }
1317        },
1318        "overrides": []
1319      },
1320      "gridPos": {
1321        "h": 8,
1322        "w": 6,
1323        "x": 18,
1324        "y": 37
1325      },
1326      "id": 17,
1327      "options": {
1328        "displayMode": "gradient",
1329        "maxVizHeight": 300,
1330        "minVizHeight": 16,
1331        "minVizWidth": 8,
1332        "namePlacement": "auto",
1333        "orientation": "horizontal",
1334        "reduceOptions": {
1335          "values": false,
1336          "calcs": [
1337            "lastNotNull"
1338          ],
1339          "fields": ""
1340        },
1341        "showUnfilled": true,
1342        "sizing": "auto",
1343        "valueMode": "color"
1344      },
1345      "pluginVersion": "11.0.0",
1346      "targets": [
1347        {
1348          "expr": "machine_known_user",
1349          "legendFormat": "{{display_name}}",
1350          "refId": "A"
1351        }
1352      ],
1353      "title": "Known User Present",
1354      "type": "bargauge"
1355    },
1356    {
1357      "collapsed": false,
1358      "gridPos": {
1359        "h": 1,
1360        "w": 24,
1361        "x": 0,
1362        "y": 45
1363      },
1364      "id": 23,
1365      "panels": [],
1366      "title": "Machine Details (Use variable to select machine)",
1367      "type": "row"
1368    },
1369    {
1370      "datasource": {
1371        "type": "prometheus",
1372        "uid": "${DS_PROMETHEUS}"
1373      },
1374      "fieldConfig": {
1375        "defaults": {
1376          "color": {
1377            "mode": "thresholds"
1378          },
1379          "mappings": [
1380            {
1381              "options": {
1382                "0": {
1383                  "color": "red",
1384                  "text": "OFF"
1385                },
1386                "1": {
1387                  "color": "green",
1388                  "text": "ON"
1389                }
1390              },
1391              "type": "value"
1392            }
1393          ],
1394          "thresholds": {
1395            "mode": "absolute",
1396            "steps": [
1397              {
1398                "color": "red",
1399                "value": null
1400              },
1401              {
1402                "color": "green",
1403                "value": 1
1404              }
1405            ]
1406          }
1407        },
1408        "overrides": []
1409      },
1410      "gridPos": {
1411        "h": 4,
1412        "w": 4,
1413        "x": 0,
1414        "y": 46
1415      },
1416      "id": 18,
1417      "options": {
1418        "colorMode": "background",
1419        "graphMode": "none",
1420        "justifyMode": "auto",
1421        "orientation": "auto",
1422        "reduceOptions": {
1423          "values": false,
1424          "calcs": [
1425            "lastNotNull"
1426          ],
1427          "fields": ""
1428        },
1429        "showPercentChange": false,
1430        "textMode": "value_and_name",
1431        "wideLayout": true
1432      },
1433      "pluginVersion": "11.0.0",
1434      "targets": [
1435        {
1436          "expr": "machine_relay_state{machine_name=\"$machine\"}",
1437          "refId": "A"
1438        }
1439      ],
1440      "title": "Relay State",
1441      "type": "stat"
1442    },
1443    {
1444      "datasource": {
1445        "type": "prometheus",
1446        "uid": "${DS_PROMETHEUS}"
1447      },
1448      "fieldConfig": {
1449        "defaults": {
1450          "color": {
1451            "mode": "thresholds"
1452          },
1453          "mappings": [
1454            {
1455              "options": {
1456                "0": {
1457                  "color": "green",
1458                  "text": "OK"
1459                },
1460                "1": {
1461                  "color": "red",
1462                  "text": "OOPS!"
1463                }
1464              },
1465              "type": "value"
1466            }
1467          ],
1468          "thresholds": {
1469            "mode": "absolute",
1470            "steps": [
1471              {
1472                "color": "green",
1473                "value": null
1474              },
1475              {
1476                "color": "red",
1477                "value": 1
1478              }
1479            ]
1480          }
1481        },
1482        "overrides": []
1483      },
1484      "gridPos": {
1485        "h": 4,
1486        "w": 4,
1487        "x": 4,
1488        "y": 46
1489      },
1490      "id": 24,
1491      "options": {
1492        "colorMode": "background",
1493        "graphMode": "none",
1494        "justifyMode": "auto",
1495        "orientation": "auto",
1496        "reduceOptions": {
1497          "values": false,
1498          "calcs": [
1499            "lastNotNull"
1500          ],
1501          "fields": ""
1502        },
1503        "showPercentChange": false,
1504        "textMode": "value_and_name",
1505        "wideLayout": true
1506      },
1507      "pluginVersion": "11.0.0",
1508      "targets": [
1509        {
1510          "expr": "machine_oops_state{machine_name=\"$machine\"}",
1511          "refId": "A"
1512        }
1513      ],
1514      "title": "Oops State",
1515      "type": "stat"
1516    },
1517    {
1518      "datasource": {
1519        "type": "prometheus",
1520        "uid": "${DS_PROMETHEUS}"
1521      },
1522      "fieldConfig": {
1523        "defaults": {
1524          "color": {
1525            "mode": "thresholds"
1526          },
1527          "mappings": [
1528            {
1529              "options": {
1530                "0": {
1531                  "color": "green",
1532                  "text": "Available"
1533                },
1534                "1": {
1535                  "color": "red",
1536                  "text": "LOCKED"
1537                }
1538              },
1539              "type": "value"
1540            }
1541          ],
1542          "thresholds": {
1543            "mode": "absolute",
1544            "steps": [
1545              {
1546                "color": "green",
1547                "value": null
1548              },
1549              {
1550                "color": "red",
1551                "value": 1
1552              }
1553            ]
1554          }
1555        },
1556        "overrides": []
1557      },
1558      "gridPos": {
1559        "h": 4,
1560        "w": 4,
1561        "x": 8,
1562        "y": 46
1563      },
1564      "id": 25,
1565      "options": {
1566        "colorMode": "background",
1567        "graphMode": "none",
1568        "justifyMode": "auto",
1569        "orientation": "auto",
1570        "reduceOptions": {
1571          "values": false,
1572          "calcs": [
1573            "lastNotNull"
1574          ],
1575          "fields": ""
1576        },
1577        "showPercentChange": false,
1578        "textMode": "value_and_name",
1579        "wideLayout": true
1580      },
1581      "pluginVersion": "11.0.0",
1582      "targets": [
1583        {
1584          "expr": "machine_lockout_state{machine_name=\"$machine\"}",
1585          "refId": "A"
1586        }
1587      ],
1588      "title": "Lockout State",
1589      "type": "stat"
1590    },
1591    {
1592      "datasource": {
1593        "type": "prometheus",
1594        "uid": "${DS_PROMETHEUS}"
1595      },
1596      "fieldConfig": {
1597        "defaults": {
1598          "color": {
1599            "mode": "thresholds"
1600          },
1601          "mappings": [],
1602          "thresholds": {
1603            "mode": "absolute",
1604            "steps": [
1605              {
1606                "color": "green",
1607                "value": null
1608              }
1609            ]
1610          },
1611          "unit": "celsius"
1612        },
1613        "overrides": []
1614      },
1615      "gridPos": {
1616        "h": 4,
1617        "w": 3,
1618        "x": 12,
1619        "y": 46
1620      },
1621      "id": 26,
1622      "options": {
1623        "colorMode": "value",
1624        "graphMode": "area",
1625        "justifyMode": "auto",
1626        "orientation": "auto",
1627        "reduceOptions": {
1628          "values": false,
1629          "calcs": [
1630            "lastNotNull"
1631          ],
1632          "fields": ""
1633        },
1634        "showPercentChange": false,
1635        "textMode": "auto",
1636        "wideLayout": true
1637      },
1638      "pluginVersion": "11.0.0",
1639      "targets": [
1640        {
1641          "expr": "machine_esp_temperature_c{machine_name=\"$machine\"}",
1642          "refId": "A"
1643        }
1644      ],
1645      "title": "Temperature",
1646      "type": "stat"
1647    },
1648    {
1649      "datasource": {
1650        "type": "prometheus",
1651        "uid": "${DS_PROMETHEUS}"
1652      },
1653      "fieldConfig": {
1654        "defaults": {
1655          "color": {
1656            "mode": "thresholds"
1657          },
1658          "mappings": [],
1659          "thresholds": {
1660            "mode": "absolute",
1661            "steps": [
1662              {
1663                "color": "red",
1664                "value": null
1665              },
1666              {
1667                "color": "orange",
1668                "value": 30
1669              },
1670              {
1671                "color": "green",
1672                "value": 60
1673              }
1674            ]
1675          },
1676          "unit": "percent"
1677        },
1678        "overrides": []
1679      },
1680      "gridPos": {
1681        "h": 4,
1682        "w": 3,
1683        "x": 15,
1684        "y": 46
1685      },
1686      "id": 27,
1687      "options": {
1688        "colorMode": "value",
1689        "graphMode": "area",
1690        "justifyMode": "auto",
1691        "orientation": "auto",
1692        "reduceOptions": {
1693          "values": false,
1694          "calcs": [
1695            "lastNotNull"
1696          ],
1697          "fields": ""
1698        },
1699        "showPercentChange": false,
1700        "textMode": "auto",
1701        "wideLayout": true
1702      },
1703      "pluginVersion": "11.0.0",
1704      "targets": [
1705        {
1706          "expr": "machine_wifi_signal_percent{machine_name=\"$machine\"}",
1707          "refId": "A"
1708        }
1709      ],
1710      "title": "WiFi Signal",
1711      "type": "stat"
1712    },
1713    {
1714      "datasource": {
1715        "type": "prometheus",
1716        "uid": "${DS_PROMETHEUS}"
1717      },
1718      "fieldConfig": {
1719        "defaults": {
1720          "color": {
1721            "mode": "thresholds"
1722          },
1723          "mappings": [],
1724          "thresholds": {
1725            "mode": "absolute",
1726            "steps": [
1727              {
1728                "color": "green",
1729                "value": null
1730              }
1731            ]
1732          },
1733          "unit": "dtdurations"
1734        },
1735        "overrides": []
1736      },
1737      "gridPos": {
1738        "h": 4,
1739        "w": 3,
1740        "x": 18,
1741        "y": 46
1742      },
1743      "id": 28,
1744      "options": {
1745        "colorMode": "value",
1746        "graphMode": "area",
1747        "justifyMode": "auto",
1748        "orientation": "auto",
1749        "reduceOptions": {
1750          "values": false,
1751          "calcs": [
1752            "lastNotNull"
1753          ],
1754          "fields": ""
1755        },
1756        "showPercentChange": false,
1757        "textMode": "auto",
1758        "wideLayout": true
1759      },
1760      "pluginVersion": "11.0.0",
1761      "targets": [
1762        {
1763          "expr": "machine_uptime_seconds{machine_name=\"$machine\"}",
1764          "refId": "A"
1765        }
1766      ],
1767      "title": "Uptime",
1768      "type": "stat"
1769    }
1770  ],
1771  "refresh": "5s",
1772  "schemaVersion": 39,
1773  "tags": [
1774    "machine-access-control",
1775    "makerspace",
1776    "rfid"
1777  ],
1778  "templating": {
1779    "list": [
1780      {
1781        "current": {},
1782        "hide": 0,
1783        "includeAll": false,
1784        "label": "Machine",
1785        "multi": false,
1786        "name": "machine",
1787        "options": [],
1788        "query": "prometheus",
1789        "refresh": 1,
1790        "regex": "/display_name=\"([^\"]+)\"/",
1791        "skipUrlSync": false,
1792        "type": "query",
1793        "datasource": {
1794          "type": "prometheus",
1795          "uid": "${DS_PROMETHEUS}"
1796        },
1797        "definition": "label_values(machine_relay_state, display_name)"
1798      },
1799      {
1800        "current": {},
1801        "hide": 2,
1802        "includeAll": false,
1803        "multi": false,
1804        "name": "DS_PROMETHEUS",
1805        "options": [],
1806        "query": "prometheus",
1807        "refresh": 1,
1808        "regex": "",
1809        "skipUrlSync": false,
1810        "type": "datasource"
1811      }
1812    ]
1813  },
1814  "time": {
1815    "from": "now-24h",
1816    "to": "now"
1817  },
1818  "timepicker": {},
1819  "timezone": "browser",
1820  "title": "Machine Access Control",
1821  "description": "https://github.com/jantman/machine-access-control/blob/main/docs/source/grafana-dashboard.json",
1822  "uid": "dm-mac-dashboard",
1823  "version": 1,
1824  "weekStart": ""
1825}