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": "dark-gray",
 528                  "text": "OK"
 529                },
 530                "1": {
 531                  "color": "red",
 532                  "text": "OOPS!"
 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": 1
 548              }
 549            ]
 550          }
 551        },
 552        "overrides": []
 553      },
 554      "gridPos": {
 555        "h": 6,
 556        "w": 8,
 557        "x": 16,
 558        "y": 5
 559      },
 560      "id": 8,
 561      "options": {
 562        "colorMode": "background",
 563        "graphMode": "none",
 564        "justifyMode": "auto",
 565        "orientation": "auto",
 566        "reduceOptions": {
 567          "values": false,
 568          "calcs": [
 569            "lastNotNull"
 570          ],
 571          "fields": ""
 572        },
 573        "showPercentChange": false,
 574        "textMode": "name",
 575        "wideLayout": true
 576      },
 577      "pluginVersion": "11.0.0",
 578      "targets": [
 579        {
 580          "expr": "machine_oops_state",
 581          "legendFormat": "{{display_name}}",
 582          "refId": "A"
 583        }
 584      ],
 585      "title": "Machine Status (Oops Button)",
 586      "type": "stat"
 587    },
 588    {
 589      "datasource": {
 590        "type": "prometheus",
 591        "uid": "${DS_PROMETHEUS}"
 592      },
 593      "fieldConfig": {
 594        "defaults": {
 595          "color": {
 596            "mode": "palette-classic"
 597          },
 598          "custom": {
 599            "axisBorderShow": false,
 600            "axisCenteredZero": false,
 601            "axisColorMode": "text",
 602            "axisLabel": "",
 603            "axisPlacement": "auto",
 604            "barAlignment": 0,
 605            "drawStyle": "line",
 606            "fillOpacity": 10,
 607            "gradientMode": "none",
 608            "hideFrom": {
 609              "tooltip": false,
 610              "viz": false,
 611              "legend": false
 612            },
 613            "insertNulls": false,
 614            "lineInterpolation": "stepAfter",
 615            "lineWidth": 2,
 616            "pointSize": 5,
 617            "scaleDistribution": {
 618              "type": "linear"
 619            },
 620            "showPoints": "never",
 621            "spanNulls": false,
 622            "stacking": {
 623              "group": "A",
 624              "mode": "none"
 625            },
 626            "thresholdsStyle": {
 627              "mode": "off"
 628            }
 629          },
 630          "mappings": [],
 631          "max": 1,
 632          "min": 0,
 633          "thresholds": {
 634            "mode": "absolute",
 635            "steps": [
 636              {
 637                "color": "green",
 638                "value": null
 639              }
 640            ]
 641          },
 642          "unit": "short"
 643        },
 644        "overrides": []
 645      },
 646      "gridPos": {
 647        "h": 8,
 648        "w": 12,
 649        "x": 0,
 650        "y": 11
 651      },
 652      "id": 9,
 653      "options": {
 654        "legend": {
 655          "calcs": [],
 656          "displayMode": "list",
 657          "placement": "bottom",
 658          "showLegend": true
 659        },
 660        "tooltip": {
 661          "mode": "multi",
 662          "sort": "none"
 663        }
 664      },
 665      "pluginVersion": "11.0.0",
 666      "targets": [
 667        {
 668          "expr": "machine_relay_state",
 669          "legendFormat": "{{display_name}}",
 670          "refId": "A"
 671        }
 672      ],
 673      "title": "Machine Relay State Over Time",
 674      "type": "timeseries"
 675    },
 676    {
 677      "datasource": {
 678        "type": "prometheus",
 679        "uid": "${DS_PROMETHEUS}"
 680      },
 681      "fieldConfig": {
 682        "defaults": {
 683          "color": {
 684            "mode": "palette-classic"
 685          },
 686          "custom": {
 687            "axisBorderShow": false,
 688            "axisCenteredZero": false,
 689            "axisColorMode": "text",
 690            "axisLabel": "",
 691            "axisPlacement": "auto",
 692            "barAlignment": 0,
 693            "drawStyle": "line",
 694            "fillOpacity": 10,
 695            "gradientMode": "none",
 696            "hideFrom": {
 697              "tooltip": false,
 698              "viz": false,
 699              "legend": false
 700            },
 701            "insertNulls": false,
 702            "lineInterpolation": "linear",
 703            "lineWidth": 1,
 704            "pointSize": 5,
 705            "scaleDistribution": {
 706              "type": "log",
 707              "log": 10
 708            },
 709            "showPoints": "never",
 710            "spanNulls": false,
 711            "stacking": {
 712              "group": "A",
 713              "mode": "none"
 714            },
 715            "thresholdsStyle": {
 716              "mode": "off"
 717            }
 718          },
 719          "mappings": [],
 720          "thresholds": {
 721            "mode": "absolute",
 722            "steps": [
 723              {
 724                "color": "green",
 725                "value": null
 726              },
 727              {
 728                "color": "yellow",
 729                "value": 60
 730              },
 731              {
 732                "color": "orange",
 733                "value": 300
 734              },
 735              {
 736                "color": "red",
 737                "value": 600
 738              }
 739            ]
 740          },
 741          "unit": "s"
 742        },
 743        "overrides": []
 744      },
 745      "gridPos": {
 746        "h": 8,
 747        "w": 12,
 748        "x": 12,
 749        "y": 11
 750      },
 751      "id": 10,
 752      "options": {
 753        "legend": {
 754          "calcs": [
 755            "lastNotNull"
 756          ],
 757          "displayMode": "table",
 758          "placement": "bottom",
 759          "showLegend": true
 760        },
 761        "tooltip": {
 762          "mode": "multi",
 763          "sort": "none"
 764        }
 765      },
 766      "pluginVersion": "11.0.0",
 767      "targets": [
 768        {
 769          "expr": "time() - machine_last_checkin_timestamp",
 770          "legendFormat": "{{display_name}}",
 771          "refId": "A"
 772        }
 773      ],
 774      "title": "Time Since Last Check-In (Log Scale)",
 775      "type": "timeseries"
 776    },
 777    {
 778      "collapsed": false,
 779      "gridPos": {
 780        "h": 1,
 781        "w": 24,
 782        "x": 0,
 783        "y": 19
 784      },
 785      "id": 21,
 786      "panels": [],
 787      "title": "Machine Health & Connectivity",
 788      "type": "row"
 789    },
 790    {
 791      "datasource": {
 792        "type": "prometheus",
 793        "uid": "${DS_PROMETHEUS}"
 794      },
 795      "fieldConfig": {
 796        "defaults": {
 797          "color": {
 798            "mode": "palette-classic"
 799          },
 800          "custom": {
 801            "axisBorderShow": false,
 802            "axisCenteredZero": false,
 803            "axisColorMode": "text",
 804            "axisLabel": "",
 805            "axisPlacement": "auto",
 806            "barAlignment": 0,
 807            "drawStyle": "line",
 808            "fillOpacity": 10,
 809            "gradientMode": "none",
 810            "hideFrom": {
 811              "tooltip": false,
 812              "viz": false,
 813              "legend": false
 814            },
 815            "insertNulls": false,
 816            "lineInterpolation": "linear",
 817            "lineWidth": 1,
 818            "pointSize": 5,
 819            "scaleDistribution": {
 820              "type": "linear"
 821            },
 822            "showPoints": "never",
 823            "spanNulls": false,
 824            "stacking": {
 825              "group": "A",
 826              "mode": "none"
 827            },
 828            "thresholdsStyle": {
 829              "mode": "off"
 830            }
 831          },
 832          "mappings": [],
 833          "thresholds": {
 834            "mode": "absolute",
 835            "steps": [
 836              {
 837                "color": "green",
 838                "value": null
 839              },
 840              {
 841                "color": "red",
 842                "value": 80
 843              }
 844            ]
 845          },
 846          "unit": "percent"
 847        },
 848        "overrides": []
 849      },
 850      "gridPos": {
 851        "h": 8,
 852        "w": 12,
 853        "x": 0,
 854        "y": 20
 855      },
 856      "id": 11,
 857      "options": {
 858        "legend": {
 859          "calcs": [
 860            "mean",
 861            "min"
 862          ],
 863          "displayMode": "table",
 864          "placement": "bottom",
 865          "showLegend": true
 866        },
 867        "tooltip": {
 868          "mode": "multi",
 869          "sort": "none"
 870        }
 871      },
 872      "pluginVersion": "11.0.0",
 873      "targets": [
 874        {
 875          "expr": "machine_wifi_signal_percent",
 876          "legendFormat": "{{display_name}}",
 877          "refId": "A"
 878        }
 879      ],
 880      "title": "WiFi Signal Strength (%)",
 881      "type": "timeseries"
 882    },
 883    {
 884      "datasource": {
 885        "type": "prometheus",
 886        "uid": "${DS_PROMETHEUS}"
 887      },
 888      "fieldConfig": {
 889        "defaults": {
 890          "color": {
 891            "mode": "palette-classic"
 892          },
 893          "custom": {
 894            "axisBorderShow": false,
 895            "axisCenteredZero": false,
 896            "axisColorMode": "text",
 897            "axisLabel": "",
 898            "axisPlacement": "auto",
 899            "barAlignment": 0,
 900            "drawStyle": "line",
 901            "fillOpacity": 10,
 902            "gradientMode": "none",
 903            "hideFrom": {
 904              "tooltip": false,
 905              "viz": false,
 906              "legend": false
 907            },
 908            "insertNulls": false,
 909            "lineInterpolation": "linear",
 910            "lineWidth": 1,
 911            "pointSize": 5,
 912            "scaleDistribution": {
 913              "type": "linear"
 914            },
 915            "showPoints": "never",
 916            "spanNulls": false,
 917            "stacking": {
 918              "group": "A",
 919              "mode": "none"
 920            },
 921            "thresholdsStyle": {
 922              "mode": "off"
 923            }
 924          },
 925          "mappings": [],
 926          "thresholds": {
 927            "mode": "absolute",
 928            "steps": [
 929              {
 930                "color": "green",
 931                "value": null
 932              },
 933              {
 934                "color": "red",
 935                "value": 80
 936              }
 937            ]
 938          },
 939          "unit": "celsius"
 940        },
 941        "overrides": []
 942      },
 943      "gridPos": {
 944        "h": 8,
 945        "w": 12,
 946        "x": 0,
 947        "y": 28
 948      },
 949      "id": 12,
 950      "options": {
 951        "legend": {
 952          "calcs": [
 953            "mean",
 954            "max"
 955          ],
 956          "displayMode": "table",
 957          "placement": "bottom",
 958          "showLegend": true
 959        },
 960        "tooltip": {
 961          "mode": "multi",
 962          "sort": "none"
 963        }
 964      },
 965      "pluginVersion": "11.0.0",
 966      "targets": [
 967        {
 968          "expr": "machine_esp_temperature_c",
 969          "legendFormat": "{{display_name}}",
 970          "refId": "A"
 971        }
 972      ],
 973      "title": "ESP32 Temperature",
 974      "type": "timeseries"
 975    },
 976    {
 977      "datasource": {
 978        "type": "prometheus",
 979        "uid": "${DS_PROMETHEUS}"
 980      },
 981      "fieldConfig": {
 982        "defaults": {
 983          "color": {
 984            "mode": "palette-classic"
 985          },
 986          "custom": {
 987            "axisBorderShow": false,
 988            "axisCenteredZero": false,
 989            "axisColorMode": "text",
 990            "axisLabel": "",
 991            "axisPlacement": "auto",
 992            "barAlignment": 0,
 993            "drawStyle": "line",
 994            "fillOpacity": 10,
 995            "gradientMode": "none",
 996            "hideFrom": {
 997              "tooltip": false,
 998              "viz": false,
 999              "legend": false
1000            },
1001            "insertNulls": false,
1002            "lineInterpolation": "linear",
1003            "lineWidth": 1,
1004            "pointSize": 5,
1005            "scaleDistribution": {
1006              "type": "log",
1007              "log": 10
1008            },
1009            "showPoints": "never",
1010            "spanNulls": false,
1011            "stacking": {
1012              "group": "A",
1013              "mode": "none"
1014            },
1015            "thresholdsStyle": {
1016              "mode": "off"
1017            }
1018          },
1019          "mappings": [],
1020          "thresholds": {
1021            "mode": "absolute",
1022            "steps": [
1023              {
1024                "color": "green",
1025                "value": null
1026              }
1027            ]
1028          },
1029          "unit": "s"
1030        },
1031        "overrides": []
1032      },
1033      "gridPos": {
1034        "h": 8,
1035        "w": 12,
1036        "x": 12,
1037        "y": 28
1038      },
1039      "id": 13,
1040      "options": {
1041        "legend": {
1042          "calcs": [
1043            "lastNotNull"
1044          ],
1045          "displayMode": "table",
1046          "placement": "bottom",
1047          "showLegend": true
1048        },
1049        "tooltip": {
1050          "mode": "multi",
1051          "sort": "none"
1052        }
1053      },
1054      "pluginVersion": "11.0.0",
1055      "targets": [
1056        {
1057          "expr": "machine_uptime_seconds",
1058          "legendFormat": "{{display_name}}",
1059          "refId": "A"
1060        }
1061      ],
1062      "title": "Machine Controller Uptime (Log Scale)",
1063      "type": "timeseries"
1064    },
1065    {
1066      "datasource": {
1067        "type": "prometheus",
1068        "uid": "${DS_PROMETHEUS}"
1069      },
1070      "fieldConfig": {
1071        "defaults": {
1072          "color": {
1073            "mode": "palette-classic"
1074          },
1075          "custom": {
1076            "axisBorderShow": false,
1077            "axisCenteredZero": false,
1078            "axisColorMode": "text",
1079            "axisLabel": "",
1080            "axisPlacement": "auto",
1081            "barAlignment": 0,
1082            "drawStyle": "line",
1083            "fillOpacity": 10,
1084            "gradientMode": "none",
1085            "hideFrom": {
1086              "tooltip": false,
1087              "viz": false,
1088              "legend": false
1089            },
1090            "insertNulls": false,
1091            "lineInterpolation": "linear",
1092            "lineWidth": 1,
1093            "pointSize": 5,
1094            "scaleDistribution": {
1095              "type": "linear"
1096            },
1097            "showPoints": "never",
1098            "spanNulls": false,
1099            "stacking": {
1100              "group": "A",
1101              "mode": "none"
1102            },
1103            "thresholdsStyle": {
1104              "mode": "off"
1105            }
1106          },
1107          "mappings": [],
1108          "thresholds": {
1109            "mode": "absolute",
1110            "steps": [
1111              {
1112                "color": "green",
1113                "value": null
1114              }
1115            ]
1116          },
1117          "unit": "dB"
1118        },
1119        "overrides": []
1120      },
1121      "gridPos": {
1122        "h": 8,
1123        "w": 12,
1124        "x": 12,
1125        "y": 20
1126      },
1127      "id": 14,
1128      "options": {
1129        "legend": {
1130          "calcs": [
1131            "mean",
1132            "min"
1133          ],
1134          "displayMode": "table",
1135          "placement": "bottom",
1136          "showLegend": true
1137        },
1138        "tooltip": {
1139          "mode": "multi",
1140          "sort": "none"
1141        }
1142      },
1143      "pluginVersion": "11.0.0",
1144      "targets": [
1145        {
1146          "expr": "machine_wifi_signal_db",
1147          "legendFormat": "{{display_name}}",
1148          "refId": "A"
1149        }
1150      ],
1151      "title": "WiFi Signal Strength (dB)",
1152      "type": "timeseries"
1153    },
1154    {
1155      "collapsed": false,
1156      "gridPos": {
1157        "h": 1,
1158        "w": 24,
1159        "x": 0,
1160        "y": 36
1161      },
1162      "id": 22,
1163      "panels": [],
1164      "title": "Usage Analytics",
1165      "type": "row"
1166    },
1167    {
1168      "datasource": {
1169        "type": "prometheus",
1170        "uid": "${DS_PROMETHEUS}"
1171      },
1172      "fieldConfig": {
1173        "defaults": {
1174          "color": {
1175            "mode": "thresholds"
1176          },
1177          "mappings": [],
1178          "thresholds": {
1179            "mode": "absolute",
1180            "steps": [
1181              {
1182                "color": "green",
1183                "value": null
1184              }
1185            ]
1186          },
1187          "unit": "dtdurations"
1188        },
1189        "overrides": []
1190      },
1191      "gridPos": {
1192        "h": 8,
1193        "w": 12,
1194        "x": 0,
1195        "y": 37
1196      },
1197      "id": 15,
1198      "options": {
1199        "displayMode": "gradient",
1200        "maxVizHeight": 300,
1201        "minVizHeight": 16,
1202        "minVizWidth": 8,
1203        "namePlacement": "auto",
1204        "orientation": "horizontal",
1205        "reduceOptions": {
1206          "values": false,
1207          "calcs": [
1208            "lastNotNull"
1209          ],
1210          "fields": ""
1211        },
1212        "showUnfilled": true,
1213        "sizing": "auto",
1214        "valueMode": "color"
1215      },
1216      "pluginVersion": "11.0.0",
1217      "targets": [
1218        {
1219          "expr": "(time() - machine_rfid_present_since_timestamp) * on() (machine_rfid_present > 0)",
1220          "legendFormat": "{{display_name}}",
1221          "refId": "A"
1222        }
1223      ],
1224      "title": "Current Session Duration",
1225      "type": "bargauge"
1226    },
1227    {
1228      "datasource": {
1229        "type": "prometheus",
1230        "uid": "${DS_PROMETHEUS}"
1231      },
1232      "fieldConfig": {
1233        "defaults": {
1234          "color": {
1235            "mode": "palette-classic"
1236          },
1237          "custom": {
1238            "hideFrom": {
1239              "tooltip": false,
1240              "viz": false,
1241              "legend": false
1242            }
1243          },
1244          "mappings": []
1245        },
1246        "overrides": []
1247      },
1248      "gridPos": {
1249        "h": 8,
1250        "w": 6,
1251        "x": 12,
1252        "y": 37
1253      },
1254      "id": 16,
1255      "options": {
1256        "legend": {
1257          "displayMode": "table",
1258          "placement": "right",
1259          "showLegend": true,
1260          "values": [
1261            "value"
1262          ]
1263        },
1264        "pieType": "donut",
1265        "tooltip": {
1266          "mode": "single",
1267          "sort": "none"
1268        }
1269      },
1270      "pluginVersion": "11.0.0",
1271      "targets": [
1272        {
1273          "expr": "sum(increase(machine_relay_state[24h])) by (machine_name)",
1274          "legendFormat": "{{display_name}}",
1275          "refId": "A"
1276        }
1277      ],
1278      "title": "Machine Usage (24h)",
1279      "type": "piechart"
1280    },
1281    {
1282      "datasource": {
1283        "type": "prometheus",
1284        "uid": "${DS_PROMETHEUS}"
1285      },
1286      "fieldConfig": {
1287        "defaults": {
1288          "color": {
1289            "mode": "thresholds"
1290          },
1291          "mappings": [
1292            {
1293              "options": {
1294                "0": {
1295                  "text": "No"
1296                },
1297                "1": {
1298                  "text": "Yes"
1299                }
1300              },
1301              "type": "value"
1302            }
1303          ],
1304          "thresholds": {
1305            "mode": "absolute",
1306            "steps": [
1307              {
1308                "color": "green",
1309                "value": null
1310              }
1311            ]
1312          }
1313        },
1314        "overrides": []
1315      },
1316      "gridPos": {
1317        "h": 8,
1318        "w": 6,
1319        "x": 18,
1320        "y": 37
1321      },
1322      "id": 17,
1323      "options": {
1324        "displayMode": "gradient",
1325        "maxVizHeight": 300,
1326        "minVizHeight": 16,
1327        "minVizWidth": 8,
1328        "namePlacement": "auto",
1329        "orientation": "horizontal",
1330        "reduceOptions": {
1331          "values": false,
1332          "calcs": [
1333            "lastNotNull"
1334          ],
1335          "fields": ""
1336        },
1337        "showUnfilled": true,
1338        "sizing": "auto",
1339        "valueMode": "color"
1340      },
1341      "pluginVersion": "11.0.0",
1342      "targets": [
1343        {
1344          "expr": "machine_known_user",
1345          "legendFormat": "{{display_name}}",
1346          "refId": "A"
1347        }
1348      ],
1349      "title": "Known User Present",
1350      "type": "bargauge"
1351    },
1352    {
1353      "collapsed": false,
1354      "gridPos": {
1355        "h": 1,
1356        "w": 24,
1357        "x": 0,
1358        "y": 45
1359      },
1360      "id": 23,
1361      "panels": [],
1362      "repeat": "machine",
1363      "repeatDirection": "v",
1364      "title": "Machine Details - $machine",
1365      "type": "row"
1366    },
1367    {
1368      "datasource": {
1369        "type": "prometheus",
1370        "uid": "${DS_PROMETHEUS}"
1371      },
1372      "fieldConfig": {
1373        "defaults": {
1374          "color": {
1375            "mode": "thresholds"
1376          },
1377          "mappings": [
1378            {
1379              "options": {
1380                "0": {
1381                  "color": "red",
1382                  "text": "OFF"
1383                },
1384                "1": {
1385                  "color": "green",
1386                  "text": "ON"
1387                }
1388              },
1389              "type": "value"
1390            }
1391          ],
1392          "thresholds": {
1393            "mode": "absolute",
1394            "steps": [
1395              {
1396                "color": "red",
1397                "value": null
1398              },
1399              {
1400                "color": "green",
1401                "value": 1
1402              }
1403            ]
1404          }
1405        },
1406        "overrides": []
1407      },
1408      "gridPos": {
1409        "h": 4,
1410        "w": 4,
1411        "x": 0,
1412        "y": 46
1413      },
1414      "id": 18,
1415      "options": {
1416        "colorMode": "background",
1417        "graphMode": "none",
1418        "justifyMode": "auto",
1419        "orientation": "auto",
1420        "reduceOptions": {
1421          "values": false,
1422          "calcs": [
1423            "lastNotNull"
1424          ],
1425          "fields": ""
1426        },
1427        "showPercentChange": false,
1428        "textMode": "value_and_name",
1429        "wideLayout": true
1430      },
1431      "pluginVersion": "11.0.0",
1432      "targets": [
1433        {
1434          "expr": "machine_relay_state{machine_name=\"$machine\"}",
1435          "refId": "A"
1436        }
1437      ],
1438      "title": "Relay State",
1439      "type": "stat"
1440    },
1441    {
1442      "datasource": {
1443        "type": "prometheus",
1444        "uid": "${DS_PROMETHEUS}"
1445      },
1446      "fieldConfig": {
1447        "defaults": {
1448          "color": {
1449            "mode": "thresholds"
1450          },
1451          "mappings": [
1452            {
1453              "options": {
1454                "0": {
1455                  "color": "green",
1456                  "text": "OK"
1457                },
1458                "1": {
1459                  "color": "red",
1460                  "text": "OOPS!"
1461                }
1462              },
1463              "type": "value"
1464            }
1465          ],
1466          "thresholds": {
1467            "mode": "absolute",
1468            "steps": [
1469              {
1470                "color": "green",
1471                "value": null
1472              },
1473              {
1474                "color": "red",
1475                "value": 1
1476              }
1477            ]
1478          }
1479        },
1480        "overrides": []
1481      },
1482      "gridPos": {
1483        "h": 4,
1484        "w": 4,
1485        "x": 4,
1486        "y": 46
1487      },
1488      "id": 24,
1489      "options": {
1490        "colorMode": "background",
1491        "graphMode": "none",
1492        "justifyMode": "auto",
1493        "orientation": "auto",
1494        "reduceOptions": {
1495          "values": false,
1496          "calcs": [
1497            "lastNotNull"
1498          ],
1499          "fields": ""
1500        },
1501        "showPercentChange": false,
1502        "textMode": "value_and_name",
1503        "wideLayout": true
1504      },
1505      "pluginVersion": "11.0.0",
1506      "targets": [
1507        {
1508          "expr": "machine_oops_state{machine_name=\"$machine\"}",
1509          "refId": "A"
1510        }
1511      ],
1512      "title": "Oops State",
1513      "type": "stat"
1514    },
1515    {
1516      "datasource": {
1517        "type": "prometheus",
1518        "uid": "${DS_PROMETHEUS}"
1519      },
1520      "fieldConfig": {
1521        "defaults": {
1522          "color": {
1523            "mode": "thresholds"
1524          },
1525          "mappings": [
1526            {
1527              "options": {
1528                "0": {
1529                  "color": "green",
1530                  "text": "Available"
1531                },
1532                "1": {
1533                  "color": "red",
1534                  "text": "LOCKED"
1535                }
1536              },
1537              "type": "value"
1538            }
1539          ],
1540          "thresholds": {
1541            "mode": "absolute",
1542            "steps": [
1543              {
1544                "color": "green",
1545                "value": null
1546              },
1547              {
1548                "color": "red",
1549                "value": 1
1550              }
1551            ]
1552          }
1553        },
1554        "overrides": []
1555      },
1556      "gridPos": {
1557        "h": 4,
1558        "w": 4,
1559        "x": 8,
1560        "y": 46
1561      },
1562      "id": 25,
1563      "options": {
1564        "colorMode": "background",
1565        "graphMode": "none",
1566        "justifyMode": "auto",
1567        "orientation": "auto",
1568        "reduceOptions": {
1569          "values": false,
1570          "calcs": [
1571            "lastNotNull"
1572          ],
1573          "fields": ""
1574        },
1575        "showPercentChange": false,
1576        "textMode": "value_and_name",
1577        "wideLayout": true
1578      },
1579      "pluginVersion": "11.0.0",
1580      "targets": [
1581        {
1582          "expr": "machine_lockout_state{machine_name=\"$machine\"}",
1583          "refId": "A"
1584        }
1585      ],
1586      "title": "Lockout State",
1587      "type": "stat"
1588    },
1589    {
1590      "datasource": {
1591        "type": "prometheus",
1592        "uid": "${DS_PROMETHEUS}"
1593      },
1594      "fieldConfig": {
1595        "defaults": {
1596          "color": {
1597            "mode": "thresholds"
1598          },
1599          "mappings": [],
1600          "thresholds": {
1601            "mode": "absolute",
1602            "steps": [
1603              {
1604                "color": "green",
1605                "value": null
1606              }
1607            ]
1608          },
1609          "unit": "celsius"
1610        },
1611        "overrides": []
1612      },
1613      "gridPos": {
1614        "h": 4,
1615        "w": 3,
1616        "x": 12,
1617        "y": 46
1618      },
1619      "id": 26,
1620      "options": {
1621        "colorMode": "value",
1622        "graphMode": "area",
1623        "justifyMode": "auto",
1624        "orientation": "auto",
1625        "reduceOptions": {
1626          "values": false,
1627          "calcs": [
1628            "lastNotNull"
1629          ],
1630          "fields": ""
1631        },
1632        "showPercentChange": false,
1633        "textMode": "auto",
1634        "wideLayout": true
1635      },
1636      "pluginVersion": "11.0.0",
1637      "targets": [
1638        {
1639          "expr": "machine_esp_temperature_c{machine_name=\"$machine\"}",
1640          "refId": "A"
1641        }
1642      ],
1643      "title": "Temperature",
1644      "type": "stat"
1645    },
1646    {
1647      "datasource": {
1648        "type": "prometheus",
1649        "uid": "${DS_PROMETHEUS}"
1650      },
1651      "fieldConfig": {
1652        "defaults": {
1653          "color": {
1654            "mode": "thresholds"
1655          },
1656          "mappings": [],
1657          "thresholds": {
1658            "mode": "absolute",
1659            "steps": [
1660              {
1661                "color": "red",
1662                "value": null
1663              },
1664              {
1665                "color": "orange",
1666                "value": 30
1667              },
1668              {
1669                "color": "green",
1670                "value": 60
1671              }
1672            ]
1673          },
1674          "unit": "percent"
1675        },
1676        "overrides": []
1677      },
1678      "gridPos": {
1679        "h": 4,
1680        "w": 3,
1681        "x": 15,
1682        "y": 46
1683      },
1684      "id": 27,
1685      "options": {
1686        "colorMode": "value",
1687        "graphMode": "area",
1688        "justifyMode": "auto",
1689        "orientation": "auto",
1690        "reduceOptions": {
1691          "values": false,
1692          "calcs": [
1693            "lastNotNull"
1694          ],
1695          "fields": ""
1696        },
1697        "showPercentChange": false,
1698        "textMode": "auto",
1699        "wideLayout": true
1700      },
1701      "pluginVersion": "11.0.0",
1702      "targets": [
1703        {
1704          "expr": "machine_wifi_signal_percent{machine_name=\"$machine\"}",
1705          "refId": "A"
1706        }
1707      ],
1708      "title": "WiFi Signal",
1709      "type": "stat"
1710    },
1711    {
1712      "datasource": {
1713        "type": "prometheus",
1714        "uid": "${DS_PROMETHEUS}"
1715      },
1716      "fieldConfig": {
1717        "defaults": {
1718          "color": {
1719            "mode": "thresholds"
1720          },
1721          "mappings": [],
1722          "thresholds": {
1723            "mode": "absolute",
1724            "steps": [
1725              {
1726                "color": "green",
1727                "value": null
1728              }
1729            ]
1730          },
1731          "unit": "dtdurations"
1732        },
1733        "overrides": []
1734      },
1735      "gridPos": {
1736        "h": 4,
1737        "w": 3,
1738        "x": 18,
1739        "y": 46
1740      },
1741      "id": 28,
1742      "options": {
1743        "colorMode": "value",
1744        "graphMode": "area",
1745        "justifyMode": "auto",
1746        "orientation": "auto",
1747        "reduceOptions": {
1748          "values": false,
1749          "calcs": [
1750            "lastNotNull"
1751          ],
1752          "fields": ""
1753        },
1754        "showPercentChange": false,
1755        "textMode": "auto",
1756        "wideLayout": true
1757      },
1758      "pluginVersion": "11.0.0",
1759      "targets": [
1760        {
1761          "expr": "machine_uptime_seconds{machine_name=\"$machine\"}",
1762          "refId": "A"
1763        }
1764      ],
1765      "title": "Uptime",
1766      "type": "stat"
1767    }
1768  ],
1769  "refresh": "5s",
1770  "schemaVersion": 39,
1771  "tags": [
1772    "machine-access-control",
1773    "makerspace",
1774    "rfid"
1775  ],
1776  "templating": {
1777    "list": [
1778      {
1779        "allValue": "",
1780        "current": {},
1781        "hide": 0,
1782        "includeAll": true,
1783        "label": "Machine",
1784        "multi": true,
1785        "name": "machine",
1786        "options": [],
1787        "query": "label_values(machine_relay_state, machine_name)",
1788        "refresh": 1,
1789        "regex": "",
1790        "skipUrlSync": false,
1791        "type": "query",
1792        "datasource": {
1793          "type": "prometheus",
1794          "uid": "${DS_PROMETHEUS}"
1795        },
1796        "definition": "label_values(machine_relay_state, machine_name)"
1797      },
1798      {
1799        "current": {},
1800        "hide": 2,
1801        "includeAll": false,
1802        "multi": false,
1803        "name": "DS_PROMETHEUS",
1804        "options": [],
1805        "query": "prometheus",
1806        "refresh": 1,
1807        "regex": "",
1808        "skipUrlSync": false,
1809        "type": "datasource"
1810      }
1811    ]
1812  },
1813  "time": {
1814    "from": "now-24h",
1815    "to": "now"
1816  },
1817  "timepicker": {},
1818  "timezone": "browser",
1819  "title": "Machine Access Control",
1820  "description": "https://github.com/jantman/machine-access-control/blob/main/docs/source/grafana-dashboard.json",
1821  "uid": "dm-mac-dashboard",
1822  "version": 1,
1823  "weekStart": ""
1824}