diff --git a/jarvis/main.py b/jarvis/main.py index d54842d..1f76ca1 100644 --- a/jarvis/main.py +++ b/jarvis/main.py @@ -6,6 +6,7 @@ from jarvis.skills.entertainement.decide import DecideSkill from jarvis.skills.entertainement.jokes import JokesSkill from jarvis.skills.entertainement.spotify import SpotifySkill from jarvis.skills.entertainement.weather import WeatherSkill +from jarvis.skills.productivity.homeassistant import HomeAssistantSkill from jarvis.skills.productivity.speedtest import SpeedTestSkill from jarvis.skills.research.wikipedia import WikipediaSkill from jarvis.utils import languages_utils, flask_utils @@ -24,6 +25,7 @@ def start(): DecideSkill().register() TimerSkill().register() WeatherSkill().register() + HomeAssistantSkill().register() # Load all skills intent_manager.load_all_skills() diff --git a/jarvis/skills/productivity/homeassistant/__init__.py b/jarvis/skills/productivity/homeassistant/__init__.py new file mode 100644 index 0000000..5f46a09 --- /dev/null +++ b/jarvis/skills/productivity/homeassistant/__init__.py @@ -0,0 +1,17 @@ +from jarvis.skills import Skill, SkillRegistering +from jarvis.skills.decorators import intent_file_handler +from jarvis.skills.productivity.homeassistant import homeassistant_client + + +class HomeAssistantSkill(Skill, metaclass=SkillRegistering): + def __init__(self, data=dict): + super().__init__("HomeAssistantSkill", data) + homeassistant_client.init() + + @intent_file_handler("homeassistant_turn_on.intent", "HATurnOn") + def handle_turn_on(self, data): + print(homeassistant_client.find_switchable_entity(data['entity'])) + + +def create_skill(data): + return HomeAssistantSkill(data) diff --git a/jarvis/skills/productivity/homeassistant/homeassistant_client.py b/jarvis/skills/productivity/homeassistant/homeassistant_client.py new file mode 100644 index 0000000..65cd10e --- /dev/null +++ b/jarvis/skills/productivity/homeassistant/homeassistant_client.py @@ -0,0 +1,84 @@ +from fuzzywuzzy import fuzz +from homeassistant_api import Client + +from jarvis.utils import config_utils + +client = None + + +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' + ] + ) + + 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 + + +def find_entity(entity, types): + """Find entity with specified name, fuzzy matching + Throws request Exceptions + (Subclasses of ConnectionError or RequestException, + raises HTTPErrors if non-Ok status code) + """ + json_data = client.get_states() + # require a score above 50% + best_score = 50 + best_entity = None + if json_data: + 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( + entity, + 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'], + "best_score": best_score} + score = fuzz.token_sort_ratio( + entity, + state['entity_id'].lower()) + if score > best_score: + best_score = score + best_entity = { + "id": state['entity_id'], + "dev_name": state['attributes'] + ['friendly_name'], + "state": state['state'], + "best_score": best_score} + except KeyError: + pass + return best_entity + + +def init(): + # init the client for the first time + get_client() diff --git a/jarvis/skills/productivity/homeassistant/vocab/fr-fr/homeassistant_turn_off.intent b/jarvis/skills/productivity/homeassistant/vocab/fr-fr/homeassistant_turn_off.intent new file mode 100644 index 0000000..ae12625 --- /dev/null +++ b/jarvis/skills/productivity/homeassistant/vocab/fr-fr/homeassistant_turn_off.intent @@ -0,0 +1,2 @@ +(éteint|arrête|arrêter) (voir|) {entity} +tu peux (éteindre|arrête) (le|la) {entity} \ No newline at end of file diff --git a/jarvis/skills/productivity/homeassistant/vocab/fr-fr/homeassistant_turn_on.intent b/jarvis/skills/productivity/homeassistant/vocab/fr-fr/homeassistant_turn_on.intent new file mode 100644 index 0000000..c43c26b --- /dev/null +++ b/jarvis/skills/productivity/homeassistant/vocab/fr-fr/homeassistant_turn_on.intent @@ -0,0 +1,4 @@ +(allume|démarre) (voir|) (la|le|) {entity} +(allume|démarre) (voir|) (l'){entity} +tu peux (allumer|démarrer) (le|la|) {entity} +tu peux (allumer|démarrer) (l'){entity} \ No newline at end of file diff --git a/requirements.txt b/requirements.txt index 564f6b9..7e75e7e 100644 --- a/requirements.txt +++ b/requirements.txt @@ -12,4 +12,6 @@ spotipy~=2.18.0 translate~=3.6.1 wikipedia~=1.4.0 SpeechRecognition~=3.8.1 -speedtest-cli~=2.1.3 \ No newline at end of file +speedtest-cli~=2.1.3 +HomeAssistant-API~=2.2.0 +fuzzywuzzy \ No newline at end of file