Last active
March 29, 2024 18:09
-
-
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…
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# 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