Find orphan definitions in yaml config files

HI,

When editing heavily in the yaml files, one (I) tend to leave changed or unused pieces of code in the files. Since they are syntactically correct, but might eg point to a sensor or device that isnt there anymore, or is renamed, the checker doesn’t find them, and doesnt create any errors. HA seems not to bother either.
Still, id like to have the code as clean as possible, and was wondering if a tool is available to check for this kind of inconsistencies.

Cheers,
Marius

It would be great to have something like this.

I don’t think there is a smart way to identify unused/orphan code.
For example: a sensor that “is not there anymore” for some people might mean that it’s really gone, for other people might mean that it’s offline maybe even just temporarily.
Same thing with renamed, how is hass to know that it is a renamed sensor vs a new one?

I do tend to leave orphan things here and there too. A solution that works for me is to force myself to have everything be part of at least one group. Then I have a script that looks for all entities that are not part of a group; and then I check just these values to find things that look odd. I just need to be really conscious/careful of the changes I make to my groups or if I see something that looks out of place in a particular group.

from requests import get
import json

states_url = 'http://HASSIP:8123/api/states?api_password=<YOURPASSWORD>'
headers = {'Content-Type': 'application/json'}


response = get(states_url, headers=headers)
states = json.loads(response.text)

dfGroups = pd.DataFrame(columns=['groupName','entity'])
allEntities = []

for s in states:
    allEntities = allEntities + [s['entity_id']]
    
    if s['entity_id'].startswith('group'):
        for e in s['attributes']['entity_id']:
            dfGroups = dfGroups.append({'groupName':s['entity_id'],'entity':e}, ignore_index=True)
                        
#exist,  but is not in a group
lst = list(set(allEntities)-set(dfGroups['entity']))
lst.sort()
print ("These exist but are not in a group")
print ([s for s in lst])

#these are defined in a group but do not exist anymore
lst = list(set(dfGroups['entity'])-set(allEntities))
lst.sort()
print ("\n\nThese are in groups but do not exist")
print ([s for s in lst])

Note that this uses a couple libraries that are not part of hass installation, but I run it from another computer that does already have them.

2 Likes

Just in case someone stumbles upon this thread and wants to use the script above:

The script is obviously using the pandas module, but is missing an import line for it. Maybe just a copy&paste error…

And to make life a little easier, I also added the verify=False option for the requests.get call in line 8. If you are using SSL for your HA server, this option prevents the script from stopping because of SSL certificate verification errors. With the option set it still gives a warning, but is running fine.

If you are too paranoid to trust your local network, feel free to remove it. :grinning:

from requests import get
import json
import pandas as pd

states_url = 'https://<HASSIP>:8123/api/states?api_password=<API password>'
headers = {'Content-Type': 'application/json'}

response = get(states_url, headers=headers, verify=False)
states = json.loads(response.text)

dfGroups = pd.DataFrame(columns=['groupName','entity'])
allEntities = []

for s in states:
    allEntities = allEntities + [s['entity_id']]

    if s['entity_id'].startswith('group'):
        for e in s['attributes']['entity_id']:
            dfGroups = dfGroups.append({'groupName':s['entity_id'],'entity':e}, ignore_index=True)

#exist,  but is not in a group
lst = list(set(allEntities)-set(dfGroups['entity']))
lst.sort()
print ("These exist but are not in a group")
print ([s for s in lst])

#these are defined in a group but do not exist anymore
lst = list(set(dfGroups['entity'])-set(allEntities))
lst.sort()
print ("\n\nThese are in groups but do not exist")
print ([s for s in lst])

we’ve been building 2 scripts, that solved this original post, for the interested:

and

credits to @NigelL