""" Create a comprehensive Smart Intersection dashboard in Grafana with proper Flux queries """ import requests import json import time from datetime import datetime # Configuration GRAFANA_URL = "http://localhost:3000" GRAFANA_USER = "admin" GRAFANA_PASSWORD = "admin" # Default password, change if you've modified it INFLUX_BUCKET = "traffic_monitoring" INFLUX_ORG = "smart-intersection-org" def get_datasource_id(): """Get the InfluxDB datasource ID""" try: response = requests.get( f"{GRAFANA_URL}/api/datasources", auth=(GRAFANA_USER, GRAFANA_PASSWORD) ) if response.status_code != 200: print(f"❌ Failed to get datasources: {response.status_code}") return None datasources = response.json() for ds in datasources: if "influx" in ds["type"].lower(): print(f"✅ Found InfluxDB datasource: {ds['name']} (ID: {ds['id']})") return ds print("❌ No InfluxDB datasource found") return None except Exception as e: print(f"❌ Error getting datasource ID: {e}") return None def create_smart_intersection_dashboard(datasource): """Create a comprehensive dashboard for the Smart Intersection application""" if not datasource: print("❌ No datasource provided, cannot create dashboard") return False print(f"Creating Smart Intersection Dashboard with datasource: {datasource['name']}") dashboard = { "dashboard": { "id": None, "uid": "smart-intersection-monitoring", "title": "Smart Intersection Monitoring", "description": "Real-time monitoring dashboard for smart intersection metrics", "tags": ["smart-intersection", "monitoring", "traffic"], "timezone": "browser", "refresh": "5s", "time": { "from": "now-15m", "to": "now" }, "panels": [ # Performance Overview Row { "id": 1, "title": "Row - Performance Metrics", "type": "row", "collapsed": False, "gridPos": {"h": 1, "w": 24, "x": 0, "y": 0} }, # FPS Gauge { "id": 2, "title": "FPS", "type": "gauge", "gridPos": {"h": 8, "w": 8, "x": 0, "y": 1}, "datasource": { "type": datasource["type"], "uid": datasource["uid"] }, "options": { "orientation": "auto", "showThresholdLabels": False, "showThresholdMarkers": True }, "fieldConfig": { "defaults": { "color": {"mode": "thresholds"}, "decimals": 1, "mappings": [], "max": 30, "min": 0, "thresholds": { "mode": "absolute", "steps": [ {"color": "red", "value": None}, {"color": "orange", "value": 15}, {"color": "green", "value": 24} ] }, "unit": "fps" }, "overrides": [] }, "targets": [ { "refId": "A", "datasource": { "type": datasource["type"], "uid": datasource["uid"] }, "query": f'from(bucket: "{INFLUX_BUCKET}")\n |> range(start: -1m)\n |> filter(fn: (r) => r._measurement == "performance")\n |> filter(fn: (r) => r._field == "fps")\n |> last()' } ] }, # Processing Time { "id": 3, "title": "Processing Time", "type": "gauge", "gridPos": {"h": 8, "w": 8, "x": 8, "y": 1}, "datasource": { "type": datasource["type"], "uid": datasource["uid"] }, "options": { "orientation": "auto", "showThresholdLabels": False, "showThresholdMarkers": True }, "fieldConfig": { "defaults": { "color": {"mode": "thresholds"}, "decimals": 1, "mappings": [], "max": 200, "min": 0, "thresholds": { "mode": "absolute", "steps": [ {"color": "green", "value": None}, {"color": "orange", "value": 80}, {"color": "red", "value": 150} ] }, "unit": "ms" }, "overrides": [] }, "targets": [ { "refId": "A", "datasource": { "type": datasource["type"], "uid": datasource["uid"] }, "query": f'from(bucket: "{INFLUX_BUCKET}")\n |> range(start: -1m)\n |> filter(fn: (r) => r._measurement == "performance")\n |> filter(fn: (r) => r._field == "processing_time_ms")\n |> last()' } ] }, # Device Info { "id": 4, "title": "Device Info", "type": "stat", "gridPos": {"h": 8, "w": 8, "x": 16, "y": 1}, "datasource": { "type": datasource["type"], "uid": datasource["uid"] }, "options": { "colorMode": "value", "graphMode": "none", "justifyMode": "auto", "orientation": "auto", "reduceOptions": { "calcs": ["lastNotNull"], "fields": "", "values": False }, "textMode": "auto" }, "fieldConfig": { "defaults": { "color": {"mode": "thresholds"}, "mappings": [ { "type": "value", "options": { "online": {"color": "green", "index": 0, "text": "🟢 Online"}, "offline": {"color": "red", "index": 1, "text": "🔴 Offline"} } } ], "thresholds": { "mode": "absolute", "steps": [ {"color": "green", "value": None} ] } }, "overrides": [] }, "targets": [ { "refId": "A", "datasource": { "type": datasource["type"], "uid": datasource["uid"] }, "query": f'from(bucket: "{INFLUX_BUCKET}")\n |> range(start: -5m)\n |> filter(fn: (r) => r._measurement == "device_info")\n |> filter(fn: (r) => r._field == "status")\n |> last()\n |> yield(name: "device_status")' }, { "refId": "B", "datasource": { "type": datasource["type"], "uid": datasource["uid"] }, "query": f'from(bucket: "{INFLUX_BUCKET}")\n |> range(start: -5m)\n |> filter(fn: (r) => r._measurement == "device_info")\n |> filter(fn: (r) => r._field == "location")\n |> last()\n |> yield(name: "location")' } ] }, # Performance History { "id": 5, "title": "Performance History", "type": "timeseries", "gridPos": {"h": 9, "w": 24, "x": 0, "y": 9}, "datasource": { "type": datasource["type"], "uid": datasource["uid"] }, "options": { "tooltip": {"mode": "multi", "sort": "none"}, "legend": {"showLegend": True}, }, "fieldConfig": { "defaults": { "color": {"mode": "palette-classic"}, "custom": { "lineInterpolation": "smooth", "fillOpacity": 10, "spanNulls": False, }, "unit": "fps" }, "overrides": [ { "matcher": {"id": "byName", "options": "processing_time_ms"}, "properties": [ {"id": "unit", "value": "ms"}, {"id": "color", "value": {"mode": "fixed", "fixedColor": "orange"}} ] } ] }, "targets": [ { "refId": "A", "datasource": { "type": datasource["type"], "uid": datasource["uid"] }, "query": f'from(bucket: "{INFLUX_BUCKET}")\n |> range(start: -15m)\n |> filter(fn: (r) => r._measurement == "performance")\n |> filter(fn: (r) => r._field == "fps")\n |> aggregateWindow(every: 2s, fn: mean, createEmpty: false)\n |> yield(name: "fps")' }, { "refId": "B", "datasource": { "type": datasource["type"], "uid": datasource["uid"] }, "query": f'from(bucket: "{INFLUX_BUCKET}")\n |> range(start: -15m)\n |> filter(fn: (r) => r._measurement == "performance")\n |> filter(fn: (r) => r._field == "processing_time_ms")\n |> aggregateWindow(every: 2s, fn: mean, createEmpty: false)\n |> yield(name: "processing_time_ms")' } ] }, # Detection Row { "id": 6, "title": "Row - Object Detection", "type": "row", "collapsed": False, "gridPos": {"h": 1, "w": 24, "x": 0, "y": 18} }, # Vehicle Count { "id": 7, "title": "Vehicle Count", "type": "stat", "gridPos": {"h": 8, "w": 8, "x": 0, "y": 19}, "datasource": { "type": datasource["type"], "uid": datasource["uid"] }, "options": { "colorMode": "value", "graphMode": "area", "justifyMode": "auto", "orientation": "auto", "reduceOptions": { "calcs": ["lastNotNull"], "fields": "", "values": False } }, "fieldConfig": { "defaults": { "color": {"mode": "thresholds"}, "mappings": [], "thresholds": { "mode": "absolute", "steps": [ {"color": "blue", "value": None} ] }, "unit": "none" }, "overrides": [] }, "targets": [ { "refId": "A", "datasource": { "type": datasource["type"], "uid": datasource["uid"] }, "query": f'from(bucket: "{INFLUX_BUCKET}")\n |> range(start: -1m)\n |> filter(fn: (r) => r._measurement == "detection_events")\n |> filter(fn: (r) => r._field == "vehicle_count")\n |> last()' } ] }, # Red Light Violations { "id": 8, "title": "Red Light Violations", "type": "stat", "gridPos": {"h": 8, "w": 8, "x": 8, "y": 19}, "datasource": { "type": datasource["type"], "uid": datasource["uid"] }, "options": { "colorMode": "value", "graphMode": "area", "justifyMode": "auto", "orientation": "auto", "reduceOptions": { "calcs": ["lastNotNull"], "fields": "", "values": False } }, "fieldConfig": { "defaults": { "color": {"mode": "thresholds"}, "mappings": [], "thresholds": { "mode": "absolute", "steps": [ {"color": "green", "value": None}, {"color": "red", "value": 1} ] }, "unit": "none" }, "overrides": [] }, "targets": [ { "refId": "A", "datasource": { "type": datasource["type"], "uid": datasource["uid"] }, "query": f'from(bucket: "{INFLUX_BUCKET}")\n |> range(start: -1h)\n |> filter(fn: (r) => r._measurement == "violation_events")\n |> filter(fn: (r) => r.violation_type == "red_light_violation")\n |> count()\n |> yield(name: "violations")' } ] }, # Traffic Light Status { "id": 9, "title": "Traffic Light Status", "type": "stat", "gridPos": {"h": 8, "w": 8, "x": 16, "y": 19}, "datasource": { "type": datasource["type"], "uid": datasource["uid"] }, "options": { "colorMode": "value", "graphMode": "none", "justifyMode": "auto", "orientation": "auto", "reduceOptions": { "calcs": ["lastNotNull"], "fields": "", "values": False }, "textMode": "auto" }, "fieldConfig": { "defaults": { "color": {"mode": "thresholds"}, "mappings": [ { "type": "value", "options": { "RED": {"color": "red", "index": 0, "text": "🔴 RED"}, "YELLOW": {"color": "yellow", "index": 1, "text": "🟡 YELLOW"}, "GREEN": {"color": "green", "index": 2, "text": "🟢 GREEN"}, "UNKNOWN": {"color": "gray", "index": 3, "text": "❓ UNKNOWN"} } } ], "thresholds": { "mode": "absolute", "steps": [ {"color": "red", "value": None} ] } }, "overrides": [] }, "targets": [ { "refId": "A", "datasource": { "type": datasource["type"], "uid": datasource["uid"] }, "query": f'from(bucket: "{INFLUX_BUCKET}")\n |> range(start: -5m)\n |> filter(fn: (r) => r._measurement == "traffic_light_status")\n |> filter(fn: (r) => r._field == "color_numeric")\n |> last()\n |> map(fn: (r) => ({{ r with _value: if r._value == 1.0 then "RED" else if r._value == 2.0 then "YELLOW" else if r._value == 3.0 then "GREEN" else "UNKNOWN" }}))' } ] }, # Detection History { "id": 10, "title": "Detection History", "type": "timeseries", "gridPos": {"h": 9, "w": 24, "x": 0, "y": 27}, "datasource": { "type": datasource["type"], "uid": datasource["uid"] }, "options": { "tooltip": {"mode": "multi", "sort": "none"}, "legend": {"showLegend": True} }, "fieldConfig": { "defaults": { "color": {"mode": "palette-classic"}, "custom": { "lineInterpolation": "linear", "fillOpacity": 10, "spanNulls": False, }, "unit": "none" }, "overrides": [] }, "targets": [ { "refId": "A", "datasource": { "type": datasource["type"], "uid": datasource["uid"] }, "query": f'from(bucket: "{INFLUX_BUCKET}")\n |> range(start: -15m)\n |> filter(fn: (r) => r._measurement == "detection_events")\n |> filter(fn: (r) => r._field == "vehicle_count")\n |> aggregateWindow(every: 5s, fn: mean, createEmpty: false)' }, { "refId": "B", "datasource": { "type": datasource["type"], "uid": datasource["uid"] }, "query": f'from(bucket: "{INFLUX_BUCKET}")\n |> range(start: -15m)\n |> filter(fn: (r) => r._measurement == "violation_events")\n |> filter(fn: (r) => r._field == "count")\n |> aggregateWindow(every: 5s, fn: sum, createEmpty: false)' } ] } ] }, "overwrite": True, "message": "Created Smart Intersection Monitoring Dashboard" } try: response = requests.post( f"{GRAFANA_URL}/api/dashboards/db", auth=(GRAFANA_USER, GRAFANA_PASSWORD), headers={"Content-Type": "application/json"}, data=json.dumps(dashboard) ) if response.status_code == 200: result = response.json() dashboard_url = f"{GRAFANA_URL}/d/{result['uid']}" print(f"✅ Dashboard created successfully: {dashboard_url}") print(f"👉 Please open this URL in your browser: {dashboard_url}") return True else: print(f"❌ Failed to create dashboard: {response.status_code}") print(f"Response: {response.text}") return False except Exception as e: print(f"❌ Error creating dashboard: {e}") return False def main(): print("===== CREATING SMART INTERSECTION DASHBOARD =====") print("This will create a comprehensive dashboard for your Smart Intersection application") # Get the InfluxDB datasource datasource = get_datasource_id() if not datasource: print("❌ Failed to get InfluxDB datasource, cannot proceed") return # Create the dashboard success = create_smart_intersection_dashboard(datasource) if success: print("\n✅ Smart Intersection Dashboard created successfully!") print("The dashboard includes:") print(" - Real-time FPS and processing time gauges") print(" - Device information panel") print(" - Performance history graph") print(" - Vehicle count statistics") print(" - Red light violation tracking") print(" - Traffic light status indicator") print(" - Detection history graph") print("\nEnsure your application is writing the following measurements to InfluxDB:") print(" - 'performance' with fields 'fps' and 'processing_time_ms'") print(" - 'detection_events' with field 'vehicle_count'") print(" - 'violation_events' with field 'count' and tag 'violation_type'") print(" - 'traffic_light' with field 'status'") else: print("\n❌ Failed to create Smart Intersection Dashboard") if __name__ == "__main__": main()