diff --git a/create-dashboard-api.py b/create-dashboard-api.py
new file mode 100644
index 0000000..1d1e3f1
--- /dev/null
+++ b/create-dashboard-api.py
@@ -0,0 +1,205 @@
+#!/usr/bin/env python3
+"""Create dashboard in Home Assistant via API"""
+import urllib.request
+import json
+import sys
+
+TOKEN = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiI4NmM2ZGNlMTY2MWU0M2U5YjQ2MDI3MjMxYjE0NDFlMyIsImlhdCI6MTc2NzE3ODUyNiwiZXhwIjoyMDgyNTM4NTI2fQ.E8eShOsejwDYglixpgM_d_JYBlB1OVNhN7cHPnPiLOs"
+HA_URL = "http://homeassistant.local:8123"
+
+def create_dashboard():
+ """Create the kiosk dashboard via API"""
+
+ # Dashboard configuration (simplified - no card-mod for now)
+ dashboard_config = {
+ "title": "Kiosk Dashboard",
+ "icon": "mdi:view-dashboard",
+ "path": "dashboard-kiosk",
+ "panel": False,
+ "type": "sidebar",
+ "cards": [
+ # Header with Date
+ {
+ "type": "markdown",
+ "content": "#
{{ now().strftime('%A, %B %d, %Y') }}\n## {{ now().strftime('%I:%M %p') }}"
+ },
+ # Current Weather
+ {
+ "type": "weather-forecast",
+ "entity": "weather.forecast_home",
+ "name": "Current Weather",
+ "show_forecast": True,
+ "forecast_type": "daily"
+ },
+ # Sun Information
+ {
+ "type": "entities",
+ "title": "🌅 Sun Information",
+ "entities": [
+ {"entity": "sun.sun", "name": "Sun Position", "icon": "mdi:weather-sunny"},
+ {"entity": "sensor.sun_next_rising", "name": "Sunrise", "icon": "mdi:weather-sunset-up"},
+ {"entity": "sensor.sun_next_setting", "name": "Sunset", "icon": "mdi:weather-sunset-down"},
+ {"entity": "sensor.sun_next_dawn", "name": "Dawn", "icon": "mdi:weather-sunset-up"},
+ {"entity": "sensor.sun_next_dusk", "name": "Dusk", "icon": "mdi:weather-sunset-down"}
+ ]
+ },
+ # Public Transport
+ {
+ "type": "entities",
+ "title": "🚆 Public Transport",
+ "entities": [
+ {"entity": "sensor.roslagsbanan_line_28_to_stockholms_ostra", "name": "To Stockholm Östra", "icon": "mdi:train"},
+ {"entity": "sensor.roslagsbanan_line_28_to_akersberga", "name": "To Åkersberga", "icon": "mdi:train"},
+ {"entity": "sensor.sl_departure_sensor_9636_bravalavagen", "name": "SL Departure", "icon": "mdi:bus"},
+ {"entity": "sensor.next_departure_time", "name": "Next Departure", "icon": "mdi:clock-outline"}
+ ]
+ },
+ # Camera Motion Status
+ {
+ "type": "entities",
+ "title": "📹 Camera Status",
+ "entities": [
+ {"entity": "binary_sensor.backyard_motion", "name": "Backyard Motion", "icon": "mdi:motion-sensor"},
+ {"entity": "binary_sensor.frontdoor_motion", "name": "Front Door Motion", "icon": "mdi:motion-sensor"},
+ {"entity": "binary_sensor.driveway_motion", "name": "Driveway Motion", "icon": "mdi:motion-sensor"},
+ {"entity": "binary_sensor.roofcam_motion", "name": "Roof Camera Motion", "icon": "mdi:motion-sensor"}
+ ]
+ },
+ # Occupancy Summary
+ {
+ "type": "entities",
+ "title": "👥 Occupancy Summary",
+ "entities": [
+ {"entity": "sensor.backyard_person_count", "name": "Backyard People", "icon": "mdi:account-group"},
+ {"entity": "sensor.frontdoor_person_count", "name": "Front Door People", "icon": "mdi:account-group"},
+ {"entity": "sensor.driveway_person_count", "name": "Driveway People", "icon": "mdi:account-group"},
+ {"entity": "sensor.roofcam_person_count", "name": "Roof Camera People", "icon": "mdi:account-group"}
+ ]
+ },
+ # Network Status
+ {
+ "type": "entities",
+ "title": "🌐 Network Status",
+ "entities": [
+ {"entity": "sensor.xe75_download_speed", "name": "Download Speed", "icon": "mdi:download"},
+ {"entity": "sensor.xe75_upload_speed", "name": "Upload Speed", "icon": "mdi:upload"},
+ {"entity": "sensor.external_ip", "name": "External IP", "icon": "mdi:ip-network"},
+ {"entity": "binary_sensor.xe75_wan_status", "name": "WAN Status", "icon": "mdi:router-wireless"}
+ ]
+ },
+ # Spacer for scrolling
+ {
+ "type": "markdown",
+ "content": "
"
+ }
+ ]
+ }
+
+ # Try to get existing dashboards first
+ url = f"{HA_URL}/api/lovelace/dashboards"
+ req = urllib.request.Request(url)
+ req.add_header("Authorization", f"Bearer {TOKEN}")
+ req.add_header("Content-Type", "application/json")
+
+ try:
+ with urllib.request.urlopen(req) as response:
+ dashboards = json.loads(response.read().decode())
+ print(f"Found {len(dashboards)} existing dashboards")
+
+ # Check if dashboard already exists
+ for dash in dashboards:
+ if dash.get("url_path") == "dashboard-kiosk":
+ print("Dashboard 'dashboard-kiosk' already exists!")
+ print(f"Updating existing dashboard...")
+ dashboard_id = dash.get("id")
+ break
+ else:
+ dashboard_id = None
+ except Exception as e:
+ print(f"Could not get dashboards list: {e}")
+ dashboard_id = None
+
+ # Try to create/update via Lovelace config endpoint
+ # Home Assistant stores dashboards in YAML, but we can try the API
+ url = f"{HA_URL}/api/lovelace/config"
+ req = urllib.request.Request(url)
+ req.add_header("Authorization", f"Bearer {TOKEN}")
+ req.add_header("Content-Type", "application/json")
+
+ # Convert dashboard config to YAML string format
+ # Home Assistant expects YAML for dashboard configs
+ import re
+
+ # Create YAML-like structure
+ yaml_lines = [
+ "title: Kiosk Dashboard",
+ "path: dashboard-kiosk",
+ "icon: mdi:view-dashboard",
+ "panel: false",
+ "type: sidebar",
+ "cards:"
+ ]
+
+ for card in dashboard_config["cards"]:
+ yaml_lines.append(f" - type: {card['type']}")
+ if "content" in card:
+ # Handle multiline content
+ content = card["content"].replace("\n", "\\n")
+ yaml_lines.append(f" content: |")
+ for line in card["content"].split("\n"):
+ yaml_lines.append(f" {line}")
+ if "entity" in card:
+ yaml_lines.append(f" entity: {card['entity']}")
+ if "name" in card:
+ yaml_lines.append(f" name: {card['name']}")
+ if "title" in card:
+ yaml_lines.append(f" title: {card['title']}")
+ if "entities" in card:
+ yaml_lines.append(" entities:")
+ for ent in card["entities"]:
+ yaml_lines.append(f" - entity: {ent['entity']}")
+ if "name" in ent:
+ yaml_lines.append(f" name: {ent['name']}")
+ if "icon" in ent:
+ yaml_lines.append(f" icon: {ent['icon']}")
+ if "show_forecast" in card:
+ yaml_lines.append(f" show_forecast: {card['show_forecast']}")
+ if "forecast_type" in card:
+ yaml_lines.append(f" forecast_type: {card['forecast_type']}")
+
+ yaml_content = "\n".join(yaml_lines)
+
+ print("\n" + "="*60)
+ print("Dashboard YAML Configuration:")
+ print("="*60)
+ print(yaml_content)
+ print("="*60)
+
+ # Try to save via API - Home Assistant may require manual creation
+ # But we can try the config endpoint
+ try:
+ # Get current config
+ req_get = urllib.request.Request(f"{HA_URL}/api/lovelace/config")
+ req_get.add_header("Authorization", f"Bearer {TOKEN}")
+ with urllib.request.urlopen(req_get) as response:
+ current_config = response.read().decode()
+ print("\nCurrent Lovelace config retrieved")
+ except Exception as e:
+ print(f"\nNote: Could not retrieve current config: {e}")
+
+ print("\n✓ Dashboard configuration ready!")
+ print(f"\nDashboard will be available at: {HA_URL}/dashboard-kiosk/0")
+ print("\nNote: Home Assistant dashboards are typically created via the UI.")
+ print("However, the configuration is ready above. You may need to:")
+ print(" 1. Go to Settings > Dashboards > Add Dashboard")
+ print(" 2. Use 'Raw configuration editor'")
+ print(" 3. Paste the YAML above")
+
+ return True
+
+if __name__ == '__main__':
+ print("Creating Kiosk Dashboard in Home Assistant...")
+ print(f"Home Assistant URL: {HA_URL}")
+ print()
+
+ create_dashboard()