#!/usr/bin/env python3 """Create dashboard by writing to Home Assistant config directory via file editor API""" import urllib.request import json import sys TOKEN = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiI4NmM2ZGNlMTY2MWU0M2U5YjQ2MDI3MjMxYjE0NDFlMyIsImlhdCI6MTc2NzE3ODUyNiwiZXhwIjoyMDgyNTM4NTI2fQ.E8eShOsejwDYglixpgM_d_JYBlB1OVNhN7cHPnPiLOs" HA_URL = "http://homeassistant.local:8123" DASHBOARD_YAML = """title: Kiosk Dashboard path: dashboard-kiosk icon: mdi:view-dashboard panel: false type: sidebar cards: - type: markdown content: | #
{{ now().strftime('%A, %B %d, %Y') }}
##
{{ now().strftime('%I:%M %p') }}
- type: weather-forecast entity: weather.forecast_home name: Current Weather show_forecast: true forecast_type: daily - 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 - 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 - 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 - 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 - 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 - type: markdown content: |




""" def write_file_via_api(file_path, content): """Write file using Home Assistant file editor API""" # Try file editor API endpoint url = f"{HA_URL}/api/file_editor/write" data = { "path": file_path, "content": content } req = urllib.request.Request(url, data=json.dumps(data).encode()) req.add_header("Authorization", f"Bearer {TOKEN}") req.add_header("Content-Type", "application/json") try: with urllib.request.urlopen(req) as response: result = json.loads(response.read().decode()) if result.get("success"): print(f"โœ“ Successfully wrote file: {file_path}") return True else: print(f"โœ— Failed to write file: {result.get('error', 'Unknown error')}") return False except urllib.error.HTTPError as e: error_msg = e.read().decode() print(f"โœ— HTTP Error {e.code}: {error_msg[:200]}") return False except Exception as e: print(f"โœ— Error: {e}") return False def create_dashboard(): """Create dashboard by writing to storage directory""" # Home Assistant stores dashboards in .storage/lovelace/ # Try different possible paths paths_to_try = [ ".storage/lovelace/dashboard-kiosk.yaml", "config/.storage/lovelace/dashboard-kiosk.yaml", "dashboard-kiosk.yaml" ] print("Attempting to create dashboard via file editor API...") print() for path in paths_to_try: print(f"Trying path: {path}") if write_file_via_api(path, DASHBOARD_YAML): print(f"\nโœ“ Dashboard created at: {path}") print(f"Dashboard URL: {HA_URL}/dashboard-kiosk/0") return True print() # If file editor doesn't work, try creating via Lovelace storage format print("Trying Lovelace storage format...") storage_data = { "title": "Kiosk Dashboard", "icon": "mdi:view-dashboard", "url_path": "dashboard-kiosk", "require_admin": False, "show_in_sidebar": True, "config": { "title": "Kiosk Dashboard", "path": "dashboard-kiosk", "icon": "mdi:view-dashboard", "panel": False, "type": "sidebar", "cards": json.loads(json.dumps([ {"type": "markdown", "content": "#
{{ now().strftime('%A, %B %d, %Y') }}
\n##
{{ now().strftime('%I:%M %p') }}
"}, {"type": "weather-forecast", "entity": "weather.forecast_home", "name": "Current Weather", "show_forecast": True, "forecast_type": "daily"}, # ... simplified for storage format ])) } } storage_path = ".storage/lovelace.dashboards" if write_file_via_api(storage_path, json.dumps(storage_data, indent=2)): return True print("\n" + "="*60) print("Could not create dashboard via API.") print("Home Assistant dashboards must be created via the UI.") print("="*60) print("\nDashboard YAML is ready in: /home/kyle/scripts/dashboard-kiosk-final.yaml") print("\nPlease create it manually:") print("1. Settings > Dashboards > Add Dashboard") print("2. Raw configuration editor > Paste YAML") return False if __name__ == '__main__': create_dashboard()