{"id":14448,"date":"2025-05-13T20:43:29","date_gmt":"2025-05-14T03:43:29","guid":{"rendered":"https:\/\/www.apolonio.com\/blog\/?p=14448"},"modified":"2025-05-13T20:43:29","modified_gmt":"2025-05-14T03:43:29","slug":"ups-dying","status":"publish","type":"post","link":"https:\/\/www.apolonio.com\/blog\/?p=14448","title":{"rendered":"UPS Dying"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">My lastman project worked, got a bunch of SMS messages when the UPS for my stack of switches died.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">I looked at when I purchased this UPS, July 2021, so yeah 4 years, need to be replaced.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">I got quality batteries, this is a very important stack.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Another thing I got done was listing devices and entities via python.  Yesterday I got it working with curl\/bash.  Here is my code for python<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">#!\/usr\/bin\/python3<br>\"\"\"<br>hassquery.py<br>Simple Python Script that uses websockets API to query devices in home assistant<br>By Larry Apolonio<br>Date : 2025-05-13<br>\"\"\"<br>import argparse<br>import asyncio<br>import json<br>import websockets<br><br># === CONFIGURATION ===<br>HA_WS_URL = \"ws:\/\/homeassistant.local:8123\/api\/websocket\"<br>ACCESS_TOKEN = \"TOKENGOESHERE\"    # Replace with your token<br><br># === PARSE ARGUMENTS ===<br>parser = argparse.ArgumentParser(description=\"List Home Assistant devices by integration.\")<br>parser.add_argument(<br>    \"-i\", \"--integration\",<br>    type=str,<br>    default=\"all\",<br>    help=\"Integration to filter by (e.g. zha, tplink, mqtt, hue). Use 'all' to list everything.\"<br>)<br>args = parser.parse_args()<br>filter_integration = args.integration.lower()<br><br>async def list_devices_by_integration():<br>    \"\"\"<br>    list_devices_by_integration<br>    Actual function to list devices<br>    \"\"\"<br>    async with websockets.connect(HA_WS_URL, max_size=10 * 1024 * 1024) as ws:<br>        # Step 1: Authenticate<br>        await ws.recv()<br>        await ws.send(json.dumps({\"type\": \"auth\", \"access_token\": ACCESS_TOKEN}))<br>        auth_response = json.loads(await ws.recv())<br>        if auth_response.get(\"type\") != \"auth_ok\":<br>            print(\"Authentication failed.\")<br>            return<br>        print(f\"Authenticated. Listing devices for integration: '{filter_integration}'\\n\")<br><br>        # Step 2: Get device registry<br>        await ws.send(json.dumps({\"id\": 1, \"type\": \"config\/device_registry\/list\"}))<br>        while True:<br>            msg = json.loads(await ws.recv())<br>            if msg.get(\"id\") == 1 and msg.get(\"type\") == \"result\":<br>                devices = msg.get(\"result\", [])<br>                break<br><br>        # Step 3: Get entity registry<br>        await ws.send(json.dumps({\"id\": 2, \"type\": \"config\/entity_registry\/list\"}))<br>        while True:<br>            msg = json.loads(await ws.recv())<br>            if msg.get(\"id\") == 2 and msg.get(\"type\") == \"result\":<br>                entities = msg.get(\"result\", [])<br>                break<br><br>        # Step 4: Build entity map<br>        entity_map = {}<br>        for ent in entities:<br>            device_id = ent.get(\"device_id\")<br>            if device_id not in entity_map:<br>                entity_map[device_id] = []<br>            entity_map[device_id].append(ent)<br><br>        # Step 5: Filter and print<br>        matched_count = 0<br>        for device in devices:<br>            device_id = device.get(\"id\")<br>            related_entities = entity_map.get(device_id, [])<br>            platforms = {e.get(\"platform\", \"\").lower() for e in related_entities}<br><br>            if filter_integration != \"all\" and filter_integration not in platforms:<br>                continue<br><br>            matched_count += 1<br>            name = device.get(\"name_by_user\") or device.get(\"name\") or \"Unnamed\"<br>            manufacturer = device.get(\"manufacturer\", \"Unknown\")<br>            model = device.get(\"model\", \"Unknown\")<br>            identifiers = device.get(\"identifiers\", [])<br>            area = device.get(\"area_id\", \"N\/A\")<br><br>            print(f\"Name         : {name}\")<br>            print(f\"Manufacturer : {manufacturer}\")<br>            print(f\"Model        : {model}\")<br>            print(f\"Area         : {area}\")<br>            print(f\"Identifiers  : {identifiers}\")<br>            print(f\"Platforms    : {', '.join(sorted(platforms)) or 'N\/A'}\")<br>            print(\"Entities     :\")<br>            for ent in related_entities:<br>                print(f\"  - {ent['entity_id']} ({ent['platform']})\")<br>            print(\"-\" * 60)<br><br>        print(f\"\\nTotal devices found: {matched_count}\")<br><br>if __name__ == '__main__':<br>    asyncio.run(list_devices_by_integration())<br><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Weight: 347.8<\/p>\n","protected":false},"excerpt":{"rendered":"<p>My lastman project worked, got a bunch of SMS messages when the UPS for my stack of switches died. I looked at when I purchased this UPS, July 2021, so yeah 4 years, need to be replaced. I got quality &hellip; <a href=\"https:\/\/www.apolonio.com\/blog\/?p=14448\">Continue reading <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[27,14,11,3,9],"tags":[],"class_list":["post-14448","post","type-post","status-publish","format-standard","hentry","category-coding","category-new-toys","category-technical","category-training","category-weighin"],"_links":{"self":[{"href":"https:\/\/www.apolonio.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/14448","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.apolonio.com\/blog\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.apolonio.com\/blog\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.apolonio.com\/blog\/index.php?rest_route=\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/www.apolonio.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=14448"}],"version-history":[{"count":1,"href":"https:\/\/www.apolonio.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/14448\/revisions"}],"predecessor-version":[{"id":14449,"href":"https:\/\/www.apolonio.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/14448\/revisions\/14449"}],"wp:attachment":[{"href":"https:\/\/www.apolonio.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=14448"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.apolonio.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=14448"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.apolonio.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=14448"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}