Skip to content

Instantly share code, notes, and snippets.

@erkr
Last active March 29, 2024 18:09
Show Gist options
  • Save erkr/45d6d82053d20001976b29e19ae2e7de to your computer and use it in GitHub Desktop.
Save erkr/45d6d82053d20001976b29e19ae2e7de to your computer and use it in GitHub Desktop.
Don't start using this script! Open the link for a better solution. This gist is deprecated! Instead of parsing the dashboard for information included in a custom:datetime-card, I found a way to move all information to the back-end and populate the date-time card using auto-entities!! See: https://github.com/a-p-z/datetime-card/issues/25#issueco…
# All credits how to use websockets to retrieve the lovelace configuration goes to https://github.com/qui3xote:
# https://github.com/custom-components/pyscript/discussions/272#discussioncomment-1709728
# This example adds a service that itteratively looks-up all custom:datetime-card based cards in a particular dashboard (where optionally a specific view can be specified)
# There it evaluates all entities if they exceed the max time configured in that card and then send a notification for them
#
# Note this latest version will itterate through all embedded cards (ie vertical stacks, confditional etc)
#
# MIT license by Eric Kreuwels
import json
import websockets
import datetime
token = 'long lived access token'
# allow to configure the token in the pyscript global config
if 'token' in pyscript.config['global']:
token = pyscript.config['global']['token']
ha_location = '127.0.0.1' #should always work in jupyter/pyscript, adjust if connecting remotely
prefix = 'ws://'
port = '8123'
api_path = '/api/websocket'
ws_server_url = prefix + ha_location + ":" + port + api_path
#dashboardTitle = "Testboard"
#example command payloads
#listDashboard = {"type": "lovelace/dashboards/list"}
#createDashboard = {"type": "lovelace/dashboards/create", "title": dashboardTitle, "url_path": dashboardUrl}
#getDashboardConfig = {"type": "lovelace/config", "url_path": dashboardUrl}
#setDashboardConfig = {"type": "lovelace/config/save", "url_path": dashboardUrl, "config": config}
#getPanels = {"type": "get_panels"}
#getConfig = {"type": "get_config"}
async def websocket_command(url, token, command: dict):
# ids are returned in the receive phase so you tie back to originating command.
# The API has feelings about these: they must increment, at least per session
websocket_command.counter += 1
command['id'] = websocket_command.counter
async with websockets.connect(url) as websocket:
log.info(websocket.recv()) #first receive will give you HA version, if it matters
await websocket.send(json.dumps({"type": "auth", "access_token": token})) #send auth
log.info(websocket.recv()) #once ok is received we go into command phase
await websocket.send(json.dumps(command))
result = websocket.recv()
log.info(result)
return json.loads(result)
websocket_command.counter = 0
#Some usage examples websocket_command:
#create a new dashboard:
#result = websocket_command(ws_server_url,token,createDashboard)
#dashboard_id = result['result']['id'] #need this to be able to delete later
#set the dashboard config:
#result = websocket_command(ws_server_url,token,setDashboardConfig)
#now delete:
#deleteDashboard = {"type": "lovelace/dashboards/delete", "dashboard_id": dashboard_id}
#websocket_command(ws_server_url,token,deleteDashboard)
def process_card(card, dashboardUrl, viewTitle):
count=0
log.info(f"Processing {viewTitle} card {card['type']}")
if "custom:datetime-card" == card['type']:
entities = card['entities']
current_date = datetime.date.today()
for entity in entities:
next_date = datetime.date.fromisoformat(state.get(entity['id'])) + datetime.timedelta(days = entity['max'])
if next_date <= current_date:
name = state.getattr(entity['id'])['friendly_name']
msg = f"Actions for {name}, due since {next_date}"
optional_data = {"url": f"/{dashboardUrl}/{viewTitle}"}
notify.mobile_app_iphone_eric(title="Maintenance Alert", message=msg, data=optional_data)
count += 1
else:
# handle nested cards if applicable
if 'cards' in card:
log.info(f"Found cards in {card['type']}")
cards = card['cards']
for subCard in cards:
count += process_card(subCard, dashboardUrl, viewTitle)
if 'card' in card:
log.info(f"Found one card in {card['type']}")
subCard = card['card']
count += process_card(subCard, dashboardUrl, viewTitle)
return count
@service
def check_maintenance_actions(dashboardUrl = "lovelace-verbruik", viewTitle = None):
getDashboardConfig = {"type": "lovelace/config", "url_path": dashboardUrl}
result = websocket_command(ws_server_url,token,getDashboardConfig)
views = result['result']['views']
count=0
for view in views:
if viewTitle != None and view['title'].lower() != viewTitle.lower():
continue;
cards = view['cards']
for card in cards:
count += process_card(card, dashboardUrl, view['title'])
input_boolean.maintenance_needed = 'on' if (count!=0) else 'off'
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment