2021-09-13 15:24:13 +02:00
|
|
|
import glob
|
|
|
|
import itertools
|
|
|
|
import json
|
|
|
|
import os
|
|
|
|
|
2021-09-12 21:50:30 +02:00
|
|
|
from fuzzywuzzy import fuzz
|
|
|
|
from homeassistant_api import Client
|
2021-09-13 15:24:13 +02:00
|
|
|
from homeassistant_api.errors import ParameterMissingError
|
2021-09-12 21:50:30 +02:00
|
|
|
|
2021-09-13 15:24:13 +02:00
|
|
|
from jarvis import get_path_file
|
2021-09-12 21:50:30 +02:00
|
|
|
from jarvis.utils import config_utils
|
|
|
|
|
|
|
|
client = None
|
2021-09-13 15:24:13 +02:00
|
|
|
overridden_entities = dict()
|
2021-09-12 21:50:30 +02:00
|
|
|
|
|
|
|
|
|
|
|
def get_entites_from_type(type: str):
|
|
|
|
return get_client().get_entities().__getattr__(type).entities
|
|
|
|
|
|
|
|
|
|
|
|
def find_switchable_entity(entity):
|
|
|
|
ha_entity = find_entity(
|
|
|
|
entity,
|
|
|
|
[
|
|
|
|
'group',
|
|
|
|
'light',
|
|
|
|
'fan',
|
|
|
|
'switch',
|
|
|
|
'scene',
|
|
|
|
'input_boolean',
|
|
|
|
'climate'
|
|
|
|
]
|
|
|
|
)
|
|
|
|
|
2021-09-13 22:09:08 +02:00
|
|
|
if ha_entity is None:
|
|
|
|
print("Can't find entity for name : " + entity)
|
|
|
|
|
2021-09-12 21:50:30 +02:00
|
|
|
return ha_entity
|
|
|
|
|
|
|
|
|
|
|
|
def get_client():
|
|
|
|
global client
|
|
|
|
if client is None:
|
|
|
|
client = Client(config_utils.get_in_secret('HOMEASSISTANT_API_URL') + "/api/",
|
|
|
|
config_utils.get_in_secret('HOMEASSISTANT_API_TOKEN'))
|
|
|
|
|
|
|
|
return client
|
|
|
|
|
|
|
|
|
2021-09-13 15:24:13 +02:00
|
|
|
def find_entity(name, types):
|
2021-09-12 21:50:30 +02:00
|
|
|
"""Find entity with specified name, fuzzy matching
|
|
|
|
Throws request Exceptions
|
|
|
|
(Subclasses of ConnectionError or RequestException,
|
|
|
|
raises HTTPErrors if non-Ok status code)
|
|
|
|
"""
|
2021-09-13 15:24:13 +02:00
|
|
|
json_data = get_client().get_states()
|
2021-09-12 21:50:30 +02:00
|
|
|
# require a score above 50%
|
|
|
|
best_score = 50
|
|
|
|
best_entity = None
|
2021-09-13 15:24:13 +02:00
|
|
|
|
|
|
|
# Check if the friendly name is overriden manually (from the config files)
|
|
|
|
if is_overridden(name):
|
|
|
|
try:
|
2021-09-13 15:46:52 +02:00
|
|
|
actionable_entity = get_client().get_entity(entity_id=get_entity_with_overridden_name(name))
|
2021-09-13 15:24:13 +02:00
|
|
|
|
|
|
|
result = {
|
|
|
|
"id": actionable_entity.entity_id,
|
|
|
|
"dev_name": actionable_entity.state['attributes']['friendly_name'],
|
|
|
|
"state": actionable_entity.state['state'],
|
|
|
|
"best_score": 101}
|
|
|
|
return result
|
|
|
|
except ParameterMissingError:
|
2021-09-13 15:46:52 +02:00
|
|
|
print("[Error] : Entity with id : " + get_entity_with_overridden_name(name) + " doesn't exists.")
|
2021-09-13 15:24:13 +02:00
|
|
|
return None
|
|
|
|
|
|
|
|
elif json_data:
|
2021-09-12 21:50:30 +02:00
|
|
|
for state in json_data:
|
|
|
|
try:
|
|
|
|
if state['entity_id'].split(".")[0] in types:
|
|
|
|
# something like temperature outside
|
|
|
|
# should score on "outside temperature sensor"
|
|
|
|
# and repetitions should not count on my behalf
|
|
|
|
score = fuzz.token_sort_ratio(
|
2021-09-13 15:24:13 +02:00
|
|
|
name,
|
2021-09-12 21:50:30 +02:00
|
|
|
state['attributes']['friendly_name'].lower())
|
|
|
|
if score > best_score:
|
|
|
|
best_score = score
|
|
|
|
best_entity = {
|
|
|
|
"id": state['entity_id'],
|
|
|
|
"dev_name": state['attributes']['friendly_name'],
|
|
|
|
"state": state['state'],
|
2021-09-13 15:24:13 +02:00
|
|
|
"best_score": best_score
|
|
|
|
}
|
|
|
|
|
2021-09-12 21:50:30 +02:00
|
|
|
score = fuzz.token_sort_ratio(
|
2021-09-13 15:24:13 +02:00
|
|
|
name,
|
2021-09-12 21:50:30 +02:00
|
|
|
state['entity_id'].lower())
|
|
|
|
if score > best_score:
|
|
|
|
best_score = score
|
|
|
|
best_entity = {
|
|
|
|
"id": state['entity_id'],
|
2021-09-13 15:24:13 +02:00
|
|
|
"dev_name": state['attributes']['friendly_name'],
|
2021-09-12 21:50:30 +02:00
|
|
|
"state": state['state'],
|
2021-09-13 15:24:13 +02:00
|
|
|
"best_score": best_score
|
|
|
|
}
|
2021-09-12 21:50:30 +02:00
|
|
|
except KeyError:
|
|
|
|
pass
|
|
|
|
return best_entity
|
|
|
|
|
|
|
|
|
2021-09-13 15:24:13 +02:00
|
|
|
def register_overrides():
|
|
|
|
global overridden_entities
|
|
|
|
files = glob.glob(os.path.dirname(get_path_file.__file__) + "/config/homeassistant/override/*.json")
|
|
|
|
|
|
|
|
for file in files:
|
|
|
|
file_json = json.load(open(file, encoding="utf8"))
|
|
|
|
friendly_names = file_json['friendly_names']
|
|
|
|
entity = file_json['entity']
|
|
|
|
|
|
|
|
overridden_entities[entity] = friendly_names
|
|
|
|
|
|
|
|
if len(overridden_entities) >= 1:
|
2021-09-13 15:46:52 +02:00
|
|
|
print("[HomeAssistantSkill] Override for entities : " + str(list(overridden_entities.keys())))
|
2021-09-13 15:24:13 +02:00
|
|
|
|
|
|
|
|
|
|
|
def is_overridden(entity_friendly_name):
|
|
|
|
values = list(itertools.chain.from_iterable(overridden_entities.values()))
|
|
|
|
if entity_friendly_name in values:
|
|
|
|
return True
|
|
|
|
|
|
|
|
return False
|
|
|
|
|
|
|
|
|
2021-09-13 15:46:52 +02:00
|
|
|
def get_entity_with_overridden_name(friendly_name):
|
|
|
|
scores = dict()
|
2021-09-13 15:24:13 +02:00
|
|
|
for key, value in overridden_entities.items():
|
2021-09-13 15:46:52 +02:00
|
|
|
for val in value:
|
|
|
|
score = fuzz.token_sort_ratio(friendly_name, val)
|
|
|
|
if score > 50:
|
|
|
|
scores[score] = key
|
|
|
|
|
|
|
|
if len(scores) >= 1:
|
|
|
|
return sorted(scores.items(), reverse=True)[0][1]
|
|
|
|
|
|
|
|
return None
|
2021-09-13 15:24:13 +02:00
|
|
|
|
|
|
|
|
2021-09-13 22:09:08 +02:00
|
|
|
def turn_on_entity(entity_id):
|
|
|
|
get_client().trigger_service("homeassistant", "turn_on", **{'entity_id': entity_id})
|
|
|
|
|
|
|
|
|
|
|
|
def turn_off_entity(entity_id):
|
|
|
|
get_client().trigger_service("homeassistant", "turn_off", **{'entity_id': entity_id})
|
|
|
|
|
|
|
|
|
|
|
|
def restart_ha():
|
|
|
|
get_client().trigger_service("homeassistant", "restart")
|
|
|
|
|
|
|
|
|
|
|
|
def shutdown_ha():
|
|
|
|
get_client().trigger_service("homeassistant", "stop")
|
|
|
|
|
|
|
|
|
2021-09-12 21:50:30 +02:00
|
|
|
def init():
|
|
|
|
# init the client for the first time
|
|
|
|
get_client()
|
2021-09-13 15:24:13 +02:00
|
|
|
|
|
|
|
# register all the overrides entity from the config/homeassistant/override/ folder
|
2021-09-13 15:46:52 +02:00
|
|
|
if not overridden_entities:
|
|
|
|
register_overrides()
|