Add create-dashboard-direct.py
This commit is contained in:
197
create-dashboard-direct.py
Normal file
197
create-dashboard-direct.py
Normal file
@@ -0,0 +1,197 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""Create dashboard directly via Home Assistant API"""
|
||||||
|
import urllib.request
|
||||||
|
import json
|
||||||
|
import sys
|
||||||
|
|
||||||
|
TOKEN = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiI4NmM2ZGNlMTY2MWU0M2U5YjQ2MDI3MjMxYjE0NDFlMyIsImlhdCI6MTc2NzE3ODUyNiwiZXhwIjoyMDgyNTM4NTI2fQ.E8eShOsejwDYglixpgM_d_JYBlB1OVNhN7cHPnPiLOs"
|
||||||
|
HA_URL = "http://homeassistant.local:8123"
|
||||||
|
|
||||||
|
# Dashboard YAML configuration
|
||||||
|
DASHBOARD_YAML = """title: Kiosk Dashboard
|
||||||
|
path: dashboard-kiosk
|
||||||
|
icon: mdi:view-dashboard
|
||||||
|
panel: false
|
||||||
|
type: sidebar
|
||||||
|
cards:
|
||||||
|
- type: markdown
|
||||||
|
content: |
|
||||||
|
# <center>{{ now().strftime('%A, %B %d, %Y') }}</center>
|
||||||
|
## <center>{{ now().strftime('%I:%M %p') }}</center>
|
||||||
|
- 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: |
|
||||||
|
<br><br><br><br><br>
|
||||||
|
"""
|
||||||
|
|
||||||
|
def create_dashboard_via_service():
|
||||||
|
"""Try to create dashboard using Home Assistant services"""
|
||||||
|
|
||||||
|
# Try using the lovelace.reload service or dashboard creation service
|
||||||
|
service_data = {
|
||||||
|
"entity_id": "all"
|
||||||
|
}
|
||||||
|
|
||||||
|
url = f"{HA_URL}/api/services/lovelace/reload_config"
|
||||||
|
req = urllib.request.Request(url, data=json.dumps(service_data).encode())
|
||||||
|
req.add_header("Authorization", f"Bearer {TOKEN}")
|
||||||
|
req.add_header("Content-Type", "application/json")
|
||||||
|
|
||||||
|
try:
|
||||||
|
with urllib.request.urlopen(req) as response:
|
||||||
|
print("✓ Reloaded Lovelace config")
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Could not reload config: {e}")
|
||||||
|
|
||||||
|
def save_dashboard_yaml():
|
||||||
|
"""Save dashboard YAML to a file for manual import"""
|
||||||
|
with open("/home/kyle/scripts/dashboard-kiosk-final.yaml", "w") as f:
|
||||||
|
f.write(DASHBOARD_YAML)
|
||||||
|
print("✓ Saved dashboard YAML to: /home/kyle/scripts/dashboard-kiosk-final.yaml")
|
||||||
|
|
||||||
|
def try_create_via_api():
|
||||||
|
"""Try various API endpoints to create dashboard"""
|
||||||
|
|
||||||
|
# Method 1: Try POST to /api/config/dashboard_config
|
||||||
|
endpoints = [
|
||||||
|
f"{HA_URL}/api/config/dashboard_config/dashboard-kiosk",
|
||||||
|
f"{HA_URL}/api/lovelace/dashboards",
|
||||||
|
f"{HA_URL}/api/config/dashboard_config",
|
||||||
|
]
|
||||||
|
|
||||||
|
dashboard_data = {
|
||||||
|
"title": "Kiosk Dashboard",
|
||||||
|
"icon": "mdi:view-dashboard",
|
||||||
|
"path": "dashboard-kiosk",
|
||||||
|
"panel": False,
|
||||||
|
"type": "sidebar",
|
||||||
|
"cards": []
|
||||||
|
}
|
||||||
|
|
||||||
|
for endpoint in endpoints:
|
||||||
|
try:
|
||||||
|
req = urllib.request.Request(endpoint, data=json.dumps(dashboard_data).encode())
|
||||||
|
req.add_header("Authorization", f"Bearer {TOKEN}")
|
||||||
|
req.add_header("Content-Type", "application/json")
|
||||||
|
req.get_method = lambda: 'POST'
|
||||||
|
|
||||||
|
with urllib.request.urlopen(req, timeout=5) as response:
|
||||||
|
result = response.read().decode()
|
||||||
|
print(f"✓ Successfully created dashboard via {endpoint}")
|
||||||
|
return True
|
||||||
|
except urllib.error.HTTPError as e:
|
||||||
|
if e.code != 404:
|
||||||
|
print(f" Endpoint {endpoint}: {e.code} - {e.read().decode()[:100]}")
|
||||||
|
except Exception as e:
|
||||||
|
pass
|
||||||
|
|
||||||
|
return False
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
print("Creating Kiosk Dashboard in Home Assistant...")
|
||||||
|
print(f"Home Assistant URL: {HA_URL}\n")
|
||||||
|
|
||||||
|
# Try API methods
|
||||||
|
if not try_create_via_api():
|
||||||
|
print("API methods not available. Home Assistant dashboards must be created via UI.")
|
||||||
|
print("\nHowever, I can provide the YAML configuration...")
|
||||||
|
|
||||||
|
# Save YAML file
|
||||||
|
save_dashboard_yaml()
|
||||||
|
|
||||||
|
print("\n" + "="*60)
|
||||||
|
print("DASHBOARD YAML (Copy this into Home Assistant):")
|
||||||
|
print("="*60)
|
||||||
|
print(DASHBOARD_YAML)
|
||||||
|
print("="*60)
|
||||||
|
print("\nTo create the dashboard:")
|
||||||
|
print("1. Open Home Assistant")
|
||||||
|
print("2. Settings > Dashboards > Add Dashboard")
|
||||||
|
print("3. Choose 'Start with an empty dashboard'")
|
||||||
|
print("4. Name it: Kiosk Dashboard")
|
||||||
|
print("5. Click ⋮ menu > Edit Dashboard > ⋮ > Raw configuration editor")
|
||||||
|
print("6. Paste the YAML above")
|
||||||
|
print("7. Save")
|
||||||
|
print(f"\nDashboard URL: {HA_URL}/dashboard-kiosk/0")
|
||||||
Reference in New Issue
Block a user