From 9bff57bbce75f83cff6376384974c6ed4ed99bb1 Mon Sep 17 00:00:00 2001 From: hrolfurinn <106666932+hrolfurinn@users.noreply.github.com> Date: Fri, 8 Jul 2022 10:55:28 +0000 Subject: [PATCH 1/7] sentence refactor iot_speakers --- queries/iot_hue.py | 726 ++++++++++++++++++++-------------------- queries/iot_speakers.py | 59 ++-- queries/sonos.py | 4 +- 3 files changed, 398 insertions(+), 391 deletions(-) diff --git a/queries/iot_hue.py b/queries/iot_hue.py index 561b74f1..ae644111 100755 --- a/queries/iot_hue.py +++ b/queries/iot_hue.py @@ -1,400 +1,400 @@ -""" - - Greynir: Natural language processing for Icelandic - - Randomness query response module - - Copyright (C) 2022 Miðeind ehf. - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see http://www.gnu.org/licenses/. - - This query module handles queries related to the generation - of random numbers, e.g. "Kastaðu tengingi", "Nefndu tölu milli 5 og 10", etc. +# """ + +# Greynir: Natural language processing for Icelandic + +# Randomness query response module + +# Copyright (C) 2022 Miðeind ehf. + +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program. If not, see http://www.gnu.org/licenses/. + +# This query module handles queries related to the generation +# of random numbers, e.g. "Kastaðu tengingi", "Nefndu tölu milli 5 og 10", etc. -""" +# """ -# TODO: add "láttu", "hafðu", "litaðu", "kveiktu" functionality. -# TODO: make the objects of sentences more modular, so that the same structure doesn't need to be written for each action -# TODO: ditto the previous comment. make the initial non-terminals general and go into specifics at the terminal level instead. -# TODO: substituion klósett, baðherbergi hugmyndÆ senda lista i javascript og profa i röð -# TODO: Embla stores old javascript code cached which has caused errors -# TODO: Cut down javascript sent to Embla -# TODO: Two specified groups or lights. -# TODO: No specified location -# TODO: Fix scene issues -# TODO: Turning on lights without using "turn on" -# TODO: Add functionality for robot-like commands "ljós í eldhúsinu", "rauður í eldhúsinu" +# # TODO: add "láttu", "hafðu", "litaðu", "kveiktu" functionality. +# # TODO: make the objects of sentences more modular, so that the same structure doesn't need to be written for each action +# # TODO: ditto the previous comment. make the initial non-terminals general and go into specifics at the terminal level instead. +# # TODO: substituion klósett, baðherbergi hugmyndÆ senda lista i javascript og profa i röð +# # TODO: Embla stores old javascript code cached which has caused errors +# # TODO: Cut down javascript sent to Embla +# # TODO: Two specified groups or lights. +# # TODO: No specified location +# # TODO: Fix scene issues +# # TODO: Turning on lights without using "turn on" +# # TODO: Add functionality for robot-like commands "ljós í eldhúsinu", "rauður í eldhúsinu" -from typing import Dict, Mapping, Optional, cast, FrozenSet -from typing_extensions import TypedDict +# from typing import Dict, Mapping, Optional, cast, FrozenSet +# from typing_extensions import TypedDict -import logging -import random -import json -import flask +# import logging +# import random +# import json +# import flask -from reynir.lemmatize import simple_lemmatize +# from reynir.lemmatize import simple_lemmatize -from query import Query, QueryStateDict, AnswerTuple -from queries import gen_answer, read_jsfile, read_grammar_file -from tree import Result, Node, TerminalNode +# from query import Query, QueryStateDict, AnswerTuple +# from queries import gen_answer, read_jsfile, read_grammar_file +# from tree import Result, Node, TerminalNode -class SmartLights(TypedDict): - selected_light: str - philips_hue: Dict[str, str] +# class SmartLights(TypedDict): +# selected_light: str +# philips_hue: Dict[str, str] -class DeviceData(TypedDict): - smartlights: SmartLights +# class DeviceData(TypedDict): +# smartlights: SmartLights -_IoT_QTYPE = "IoT" +# _IoT_QTYPE = "IoT" -TOPIC_LEMMAS = [ - "ljós", - "kveikja", - "litur", - "birta", - "hækka", - "stemmning", - "sena", - "stemming", - "stemning", -] +# TOPIC_LEMMAS = [ +# "ljós", +# "kveikja", +# "litur", +# "birta", +# "hækka", +# "stemmning", +# "sena", +# "stemming", +# "stemning", +# ] -def help_text(lemma: str) -> str: - """Help text to return when query.py is unable to parse a query but - one of the above lemmas is found in it""" - return "Ég skil þig ef þú segir til dæmis: {0}.".format( - random.choice( - ( - "Kveiktu á ljósunum inni í eldhúsi", - "Slökktu á leslampanum", - "Breyttu lit lýsingarinnar í stofunni í bláan", - "Gerðu ljósið í borðstofunni bjartara", - "Stilltu á bjartasta niðri í kjallara", - ) - ) - ) +# def help_text(lemma: str) -> str: +# """Help text to return when query.py is unable to parse a query but +# one of the above lemmas is found in it""" +# return "Ég skil þig ef þú segir til dæmis: {0}.".format( +# random.choice( +# ( +# "Kveiktu á ljósunum inni í eldhúsi", +# "Slökktu á leslampanum", +# "Breyttu lit lýsingarinnar í stofunni í bláan", +# "Gerðu ljósið í borðstofunni bjartara", +# "Stilltu á bjartasta niðri í kjallara", +# ) +# ) +# ) -_COLORS = { - "gulur": 60 * 65535 / 360, - "rauður": 360 * 65535 / 360, - "grænn": 120 * 65535 / 360, - "blár": 240 * 65535 / 360, - "ljósblár": 180 * 65535 / 360, - "bleikur": 300 * 65535 / 360, - "hvítur": [], - "fjólublár": [], - "brúnn": [], - "appelsínugulur": [], -} +# _COLORS = { +# "gulur": 60 * 65535 / 360, +# "rauður": 360 * 65535 / 360, +# "grænn": 120 * 65535 / 360, +# "blár": 240 * 65535 / 360, +# "ljósblár": 180 * 65535 / 360, +# "bleikur": 300 * 65535 / 360, +# "hvítur": [], +# "fjólublár": [], +# "brúnn": [], +# "appelsínugulur": [], +# } -# This module wants to handle parse trees for queries -HANDLE_TREE = True +# # This module wants to handle parse trees for queries +# HANDLE_TREE = True -# The grammar nonterminals this module wants to handle -QUERY_NONTERMINALS = {"QIoT"} +# # The grammar nonterminals this module wants to handle +# QUERY_NONTERMINALS = {"QIoT"} -# The context-free grammar for the queries recognized by this plug-in module -# GRAMMAR = read_grammar_file("iot_hue") +# # The context-free grammar for the queries recognized by this plug-in module +# # GRAMMAR = read_grammar_file("iot_hue") -GRAMMAR = read_grammar_file( - "iot_hue", color_names=" | ".join(f"'{color}:lo'" for color in _COLORS.keys()) -) +# GRAMMAR = read_grammar_file( +# "iot_hue", color_names=" | ".join(f"'{color}:lo'" for color in _COLORS.keys()) +# ) -def QIoTQuery(node: Node, params: QueryStateDict, result: Result) -> None: - result.qtype = _IoT_QTYPE +# def QIoTQuery(node: Node, params: QueryStateDict, result: Result) -> None: +# result.qtype = _IoT_QTYPE -def QIoTColorWord(node: Node, params: QueryStateDict, result: Result) -> None: - result.changing_color = True - - -def QIoTSceneWord(node: Node, params: QueryStateDict, result: Result) -> None: - result.changing_scene = True +# def QIoTColorWord(node: Node, params: QueryStateDict, result: Result) -> None: +# result.changing_color = True + + +# def QIoTSceneWord(node: Node, params: QueryStateDict, result: Result) -> None: +# result.changing_scene = True -def QIoTBrightnessWord(node: Node, params: QueryStateDict, result: Result) -> None: - result.changing_brightness = True +# def QIoTBrightnessWord(node: Node, params: QueryStateDict, result: Result) -> None: +# result.changing_brightness = True -def QIoTTurnOnLightsRest(node: Node, params: QueryStateDict, result: Result) -> None: - result.action = "turn_on" - if "hue_obj" not in result: - result["hue_obj"] = {"on": True} - else: - result["hue_obj"]["on"] = True +# def QIoTTurnOnLightsRest(node: Node, params: QueryStateDict, result: Result) -> None: +# result.action = "turn_on" +# if "hue_obj" not in result: +# result["hue_obj"] = {"on": True} +# else: +# result["hue_obj"]["on"] = True -def QIoTTurnOffLightsRest(node: Node, params: QueryStateDict, result: Result) -> None: - result.action = "turn_off" - if "hue_obj" not in result: - result["hue_obj"] = {"on": False} - else: - result["hue_obj"]["on"] = False +# def QIoTTurnOffLightsRest(node: Node, params: QueryStateDict, result: Result) -> None: +# result.action = "turn_off" +# if "hue_obj" not in result: +# result["hue_obj"] = {"on": False} +# else: +# result["hue_obj"]["on"] = False -def QIoTNewColor(node: Node, params: QueryStateDict, result: Result) -> None: - result.action = "set_color" - print(result.color_name) - color_hue = _COLORS.get(result.color_name, None) - print(color_hue) - if color_hue is not None: - if "hue_obj" not in result: - result["hue_obj"] = {"on": True, "hue": int(color_hue)} - else: - result["hue_obj"]["hue"] = int(color_hue) - result["hue_obj"]["on"] = True +# def QIoTNewColor(node: Node, params: QueryStateDict, result: Result) -> None: +# result.action = "set_color" +# print(result.color_name) +# color_hue = _COLORS.get(result.color_name, None) +# print(color_hue) +# if color_hue is not None: +# if "hue_obj" not in result: +# result["hue_obj"] = {"on": True, "hue": int(color_hue)} +# else: +# result["hue_obj"]["hue"] = int(color_hue) +# result["hue_obj"]["on"] = True -def QIoTMoreBrighterOrHigher( - node: Node, params: QueryStateDict, result: Result -) -> None: - result.action = "increase_brightness" - if "hue_obj" not in result: - result["hue_obj"] = {"on": True, "bri_inc": 64} - else: - result["hue_obj"]["bri_inc"] = 64 - result["hue_obj"]["on"] = True +# def QIoTMoreBrighterOrHigher( +# node: Node, params: QueryStateDict, result: Result +# ) -> None: +# result.action = "increase_brightness" +# if "hue_obj" not in result: +# result["hue_obj"] = {"on": True, "bri_inc": 64} +# else: +# result["hue_obj"]["bri_inc"] = 64 +# result["hue_obj"]["on"] = True - -def QIoTLessDarkerOrLower(node: Node, params: QueryStateDict, result: Result) -> None: - result.action = "decrease_brightness" - if "hue_obj" not in result: - result["hue_obj"] = {"bri_inc": -64} - else: - result["hue_obj"]["bri_inc"] = -64 - - -def QIoTIncreaseVerb(node: Node, params: QueryStateDict, result: Result) -> None: - result.action = "increase_brightness" - if "hue_obj" not in result: - result["hue_obj"] = {"on": True, "bri_inc": 64} - else: - result["hue_obj"]["bri_inc"] = 64 - result["hue_obj"]["on"] = True - - -def QIoTDecreaseVerb(node: Node, params: QueryStateDict, result: Result) -> None: - result.action = "decrease_brightness" - if "hue_obj" not in result: - result["hue_obj"] = {"bri_inc": -64} - else: - result["hue_obj"]["bri_inc"] = -64 - - -def QIoTBrightest(node: Node, params: QueryStateDict, result: Result) -> None: - result.action = "decrease_brightness" - if "hue_obj" not in result: - result["hue_obj"] = {"bri": 255} - else: - result["hue_obj"]["bri"] = 255 - - -def QIoTDarkest(node: Node, params: QueryStateDict, result: Result) -> None: - result.action = "decrease_brightness" - if "hue_obj" not in result: - result["hue_obj"] = {"bri": 0} - else: - result["hue_obj"]["bri"] = 0 - - -def QIoTNewScene(node: Node, params: QueryStateDict, result: Result) -> None: - result.action = "set_scene" - scene_name = result.get("scene_name", None) - print("scene: " + scene_name) - if scene_name is not None: - if "hue_obj" not in result: - result["hue_obj"] = {"on": True, "scene": scene_name} - else: - result["hue_obj"]["scene"] = scene_name - result["hue_obj"]["on"] = True - - -def QIoTColorName(node: Node, params: QueryStateDict, result: Result) -> None: - result["color_name"] = ( - node.first_child(lambda x: True).string_self().strip("'").split(":")[0] - ) - - -def QIoTSceneName(node: Node, params: QueryStateDict, result: Result) -> None: - result["scene_name"] = result._indefinite - print("scene: " + result.get("scene_name", None)) - - -def QIoTGroupName(node: Node, params: QueryStateDict, result: Result) -> None: - result["group_name"] = result._indefinite - - -def QIoTLightName(node: Node, params: QueryStateDict, result: Result) -> None: - result["light_name"] = result._indefinite - - -def QIoTLightsBanwords(node: Node, params: QueryStateDict, result: Result) -> None: - result.abort = True - - -# Convert color name into hue -# Taken from home.py -_COLOR_NAME_TO_CIE: Mapping[str, float] = { - "gulur": 60 * 65535 / 360, - "grænn": 120 * 65535 / 360, - "ljósblár": 180 * 65535 / 360, - "blár": 240 * 65535 / 360, - "bleikur": 300 * 65535 / 360, - "rauður": 360 * 65535 / 360, - # "Rauð": 360 * 65535 / 360, -} - -_SPEAKER_WORDS: FrozenSet[str] = frozenset( - ( - "tónlist", - "hátalari", - "bylgja", - "útvarp", - "útvarpsstöð", - "útvarp saga", - "gullbylgja", - "x-ið", - "léttbylgjan", - "rás 1", - "rás 2", - "rondo", - "rondó", - "fm 957", - "fm957", - "fm-957", - "k-100", - "k 100", - "kk 100", - "k hundrað", - "kk hundrað", - "x977", - "x 977", - "x-977", - "x-ið 977", - "x-ið", - "retro", - "kiss fm", - "flassbakk", - "flassbakk fm", - "útvarp hundraðið", - "útvarp 101", - "útvarp hundraðogeinn", - "útvarp hundrað og einn", - "útvarp hundrað einn", - "útvarp hundrað 1", - "útvarp", - ) -) - - -def sentence(state: QueryStateDict, result: Result) -> None: - """Called when sentence processing is complete""" - q: Query = state["query"] - if result.get("abort"): - q.set_error("E_QUERY_NOT_UNDERSTOOD") - # lemmas = set( - # i[0].root(state, result.params) - # for i in result.enum_descendants(lambda x: isinstance(x, TerminalNode)) - # ) - # if not _SPEAKER_WORDS.isdisjoint(lemmas): - # print("matched with music word list") - # q.set_error("E_QUERY_NOT_UNDERSTOOD") - # return - changing_color = result.get("changing_color", False) - changing_scene = result.get("changing_scene", False) - changing_brightness = result.get("changing_brightness", False) - print("error?", sum((changing_color, changing_scene, changing_brightness)) > 1) - if ( - sum((changing_color, changing_scene, changing_brightness)) > 1 - or "qtype" not in result - ): - q.set_error("E_QUERY_NOT_UNDERSTOOD") - return - - q.set_qtype(result.qtype) - - smartdevice_type = "iot_lights" - client_id = str(q.client_id) - print("client_id:", client_id) - - # Fetch relevant data from the device_data table to perform an action on the lights - device_data = cast(Optional[DeviceData], q.client_data(smartdevice_type)) - print("location :", q.location) - print("device data :", device_data) - - selected_light: Optional[str] = None - print("selected light:", selected_light) - hue_credentials: Optional[Dict[str, str]] = None - - if device_data is not None: - dev = device_data - assert dev is not None - light = dev.get("philips_hue") - hue_credentials = light.get("credentials") - bridge_ip = hue_credentials.get("ip_address") - username = hue_credentials.get("username") - - if not device_data or not hue_credentials: - answer = "Það vantar að tengja Philips Hub-inn." - q.set_answer(*gen_answer(answer)) - return - - # Successfully matched a query type - print("bridge_ip: ", bridge_ip) - print("username: ", username) - print("selected light :", selected_light) - print("hue credentials :", hue_credentials) - - try: - # kalla í javascripts stuff - light_or_group_name = result.get("light_name", result.get("group_name", "")) - color_name = result.get("color_name", "") - print("GROUP NAME:", light_or_group_name) - print("COLOR NAME:", color_name) - print(result.hue_obj) - q.set_answer( - *gen_answer( - "ég var að kveikja ljósin! " - # + group_name - # + " " - # + color_name - # + " " - # + result.action - # + " " - # + str(result.hue_obj.get("hue", "enginn litur")) - ) - ) - js = ( - read_jsfile("IoT_Embla/fuse.js") - + f"var BRIDGE_IP = '{bridge_ip}';var USERNAME = '{username}';" - + read_jsfile("IoT_Embla/Philips_Hue/fuse_search.js") - + read_jsfile("IoT_Embla/Philips_Hue/lights.js") - + read_jsfile("IoT_Embla/Philips_Hue/set_lights.js") - ) - js += f"setLights('{light_or_group_name}', '{json.dumps(result.hue_obj)}');" - q.set_command(js) - except Exception as e: - logging.warning("Exception while processing random query: {0}".format(e)) - q.set_error("E_EXCEPTION: {0}".format(e)) - raise - - -# f"var BRIDGE_IP = '192.168.1.68';var USERNAME = 'p3obluiXT13IbHMpp4X63ZvZnpNRdbqqMt723gy2';" + +# def QIoTLessDarkerOrLower(node: Node, params: QueryStateDict, result: Result) -> None: +# result.action = "decrease_brightness" +# if "hue_obj" not in result: +# result["hue_obj"] = {"bri_inc": -64} +# else: +# result["hue_obj"]["bri_inc"] = -64 + + +# def QIoTIncreaseVerb(node: Node, params: QueryStateDict, result: Result) -> None: +# result.action = "increase_brightness" +# if "hue_obj" not in result: +# result["hue_obj"] = {"on": True, "bri_inc": 64} +# else: +# result["hue_obj"]["bri_inc"] = 64 +# result["hue_obj"]["on"] = True + + +# def QIoTDecreaseVerb(node: Node, params: QueryStateDict, result: Result) -> None: +# result.action = "decrease_brightness" +# if "hue_obj" not in result: +# result["hue_obj"] = {"bri_inc": -64} +# else: +# result["hue_obj"]["bri_inc"] = -64 + + +# def QIoTBrightest(node: Node, params: QueryStateDict, result: Result) -> None: +# result.action = "decrease_brightness" +# if "hue_obj" not in result: +# result["hue_obj"] = {"bri": 255} +# else: +# result["hue_obj"]["bri"] = 255 + + +# def QIoTDarkest(node: Node, params: QueryStateDict, result: Result) -> None: +# result.action = "decrease_brightness" +# if "hue_obj" not in result: +# result["hue_obj"] = {"bri": 0} +# else: +# result["hue_obj"]["bri"] = 0 + + +# def QIoTNewScene(node: Node, params: QueryStateDict, result: Result) -> None: +# result.action = "set_scene" +# scene_name = result.get("scene_name", None) +# print("scene: " + scene_name) +# if scene_name is not None: +# if "hue_obj" not in result: +# result["hue_obj"] = {"on": True, "scene": scene_name} +# else: +# result["hue_obj"]["scene"] = scene_name +# result["hue_obj"]["on"] = True + + +# def QIoTColorName(node: Node, params: QueryStateDict, result: Result) -> None: +# result["color_name"] = ( +# node.first_child(lambda x: True).string_self().strip("'").split(":")[0] +# ) + + +# def QIoTSceneName(node: Node, params: QueryStateDict, result: Result) -> None: +# result["scene_name"] = result._indefinite +# print("scene: " + result.get("scene_name", None)) + + +# def QIoTGroupName(node: Node, params: QueryStateDict, result: Result) -> None: +# result["group_name"] = result._indefinite + + +# def QIoTLightName(node: Node, params: QueryStateDict, result: Result) -> None: +# result["light_name"] = result._indefinite + + +# def QIoTLightsBanwords(node: Node, params: QueryStateDict, result: Result) -> None: +# result.abort = True + + +# # Convert color name into hue +# # Taken from home.py +# _COLOR_NAME_TO_CIE: Mapping[str, float] = { +# "gulur": 60 * 65535 / 360, +# "grænn": 120 * 65535 / 360, +# "ljósblár": 180 * 65535 / 360, +# "blár": 240 * 65535 / 360, +# "bleikur": 300 * 65535 / 360, +# "rauður": 360 * 65535 / 360, +# # "Rauð": 360 * 65535 / 360, +# } + +# _SPEAKER_WORDS: FrozenSet[str] = frozenset( +# ( +# "tónlist", +# "hátalari", +# "bylgja", +# "útvarp", +# "útvarpsstöð", +# "útvarp saga", +# "gullbylgja", +# "x-ið", +# "léttbylgjan", +# "rás 1", +# "rás 2", +# "rondo", +# "rondó", +# "fm 957", +# "fm957", +# "fm-957", +# "k-100", +# "k 100", +# "kk 100", +# "k hundrað", +# "kk hundrað", +# "x977", +# "x 977", +# "x-977", +# "x-ið 977", +# "x-ið", +# "retro", +# "kiss fm", +# "flassbakk", +# "flassbakk fm", +# "útvarp hundraðið", +# "útvarp 101", +# "útvarp hundraðogeinn", +# "útvarp hundrað og einn", +# "útvarp hundrað einn", +# "útvarp hundrað 1", +# "útvarp", +# ) +# ) + + +# def sentence(state: QueryStateDict, result: Result) -> None: +# """Called when sentence processing is complete""" +# q: Query = state["query"] +# if result.get("abort"): +# q.set_error("E_QUERY_NOT_UNDERSTOOD") +# # lemmas = set( +# # i[0].root(state, result.params) +# # for i in result.enum_descendants(lambda x: isinstance(x, TerminalNode)) +# # ) +# # if not _SPEAKER_WORDS.isdisjoint(lemmas): +# # print("matched with music word list") +# # q.set_error("E_QUERY_NOT_UNDERSTOOD") +# # return +# changing_color = result.get("changing_color", False) +# changing_scene = result.get("changing_scene", False) +# changing_brightness = result.get("changing_brightness", False) +# print("error?", sum((changing_color, changing_scene, changing_brightness)) > 1) +# if ( +# sum((changing_color, changing_scene, changing_brightness)) > 1 +# or "qtype" not in result +# ): +# q.set_error("E_QUERY_NOT_UNDERSTOOD") +# return + +# q.set_qtype(result.qtype) + +# smartdevice_type = "iot_lights" +# client_id = str(q.client_id) +# print("client_id:", client_id) + +# # Fetch relevant data from the device_data table to perform an action on the lights +# device_data = cast(Optional[DeviceData], q.client_data(smartdevice_type)) +# print("location :", q.location) +# print("device data :", device_data) + +# selected_light: Optional[str] = None +# print("selected light:", selected_light) +# hue_credentials: Optional[Dict[str, str]] = None + +# if device_data is not None: +# dev = device_data +# assert dev is not None +# light = dev.get("philips_hue") +# hue_credentials = light.get("credentials") +# bridge_ip = hue_credentials.get("ip_address") +# username = hue_credentials.get("username") + +# if not device_data or not hue_credentials: +# answer = "Það vantar að tengja Philips Hub-inn." +# q.set_answer(*gen_answer(answer)) +# return + +# # Successfully matched a query type +# print("bridge_ip: ", bridge_ip) +# print("username: ", username) +# print("selected light :", selected_light) +# print("hue credentials :", hue_credentials) + +# try: +# # kalla í javascripts stuff +# light_or_group_name = result.get("light_name", result.get("group_name", "")) +# color_name = result.get("color_name", "") +# print("GROUP NAME:", light_or_group_name) +# print("COLOR NAME:", color_name) +# print(result.hue_obj) +# q.set_answer( +# *gen_answer( +# "ég var að kveikja ljósin! " +# # + group_name +# # + " " +# # + color_name +# # + " " +# # + result.action +# # + " " +# # + str(result.hue_obj.get("hue", "enginn litur")) +# ) +# ) +# js = ( +# read_jsfile("IoT_Embla/fuse.js") +# + f"var BRIDGE_IP = '{bridge_ip}';var USERNAME = '{username}';" +# + read_jsfile("IoT_Embla/Philips_Hue/fuse_search.js") +# + read_jsfile("IoT_Embla/Philips_Hue/lights.js") +# + read_jsfile("IoT_Embla/Philips_Hue/set_lights.js") +# ) +# js += f"setLights('{light_or_group_name}', '{json.dumps(result.hue_obj)}');" +# q.set_command(js) +# except Exception as e: +# logging.warning("Exception while processing random query: {0}".format(e)) +# q.set_error("E_EXCEPTION: {0}".format(e)) +# raise + + +# # f"var BRIDGE_IP = '192.168.1.68';var USERNAME = 'p3obluiXT13IbHMpp4X63ZvZnpNRdbqqMt723gy2';" diff --git a/queries/iot_speakers.py b/queries/iot_speakers.py index db409b10..3735345e 100644 --- a/queries/iot_speakers.py +++ b/queries/iot_speakers.py @@ -275,28 +275,6 @@ def QIoTSpeakerUtvarpSudurland( result.station = "Útvarp Suðurland" -def call_sonos_client(sonos_client, result): - """Call the appropriate function in the SonosClient based on the result""" - handler_func = _HANDLER_MAP[result.qkey][0] - if result.get("station") is not None: - radio_url = _RADIO_STREAMS.get(f"{result.station}") - response = getattr(sonos_client, handler_func)(radio_url) - return response - else: - response = getattr(sonos_client, handler_func)() - return response - - -# Map of query keys to handler functions and the corresponding answer string for Embla -_HANDLER_MAP = { - "turn_on": ["toggle_play", "Ég kveikti á tónlist"], - "turn_off": ["toggle_pause", "Ég slökkti á tónlist"], - "increase_volume": ["increase_volume", "Ég hækkaði í tónlistinni"], - "decrease_volume": ["decrease_volume", "Ég lækkaði í tónlistinni"], - "radio": ["play_radio_stream", "Ég setti á útvarpstöðina"], -} - - def sentence(state: QueryStateDict, result: Result) -> None: """Called when sentence processing is complete""" print("sentence") @@ -305,7 +283,7 @@ def sentence(state: QueryStateDict, result: Result) -> None: result.qkey = "turn_on" if result.qkey == "turn_on" and result.target == "radio": result.qkey = "radio" - if "qtype" in result and "qkey" in result: + if "qtype" in result: print("IF QTYPE AND QKEY") try: q.set_qtype(result.qtype) @@ -316,13 +294,42 @@ def sentence(state: QueryStateDict, result: Result) -> None: device_data, q.client_id, group_name=result.get("group_name") ) print("JUST AFTER SONOS CLIENT") - response = call_sonos_client(sonos_client, result) + # Map of query keys to handler functions and the corresponding answer string for Embla + radio_url = _RADIO_STREAMS.get(result.get("station")) + handler_map = { + "turn_on": [ + sonos_client.toggle_play, + [], + "Ég kveikti á tónlist", + ], + "turn_off": [ + sonos_client.toggle_pause, + [], + "Ég slökkti á tónlist", + ], + "increase_volume": [ + sonos_client.increase_volume, + [], + "Ég hækkaði í tónlistinni", + ], + "decrease_volume": [ + sonos_client.decrease_volume, + [], + "Ég lækkaði í tónlistinni", + ], + "radio": [ + sonos_client.play_radio_stream, + [radio_url], + "Ég setti á útvarpstöðina", + ], + } + handler, args, answer = handler_map.get(result.qkey) + response = handler(*args) if response == "Group not found": text_ans = f"Herbergið '{result.group_name}' fannst ekki. Vinsamlegast athugaðu í Sonos appinu hvort nafnið sé rétt." else: - handler_answer = _HANDLER_MAP[result.qkey][1] + handler_answer = answer text_ans = handler_answer - answer = ( dict(answer=text_ans), text_ans, diff --git a/queries/sonos.py b/queries/sonos.py index 5e969ceb..15ea25d2 100644 --- a/queries/sonos.py +++ b/queries/sonos.py @@ -78,7 +78,7 @@ from util import read_api_key from queries import query_json_api, post_to_json_api from query import Query -from typing import Dict +from typing import Dict, Optional import json @@ -377,7 +377,7 @@ def _create_or_join_session(self): ------------------------------------- PUBLIC METHODS -------------------------------------------------------------------------------- """ - def play_radio_stream(self, radio_url: str): + def play_radio_stream(self, radio_url): #: Optional[str] = self._device_data.get] print("play radio stream") session_id = self._create_or_join_session() From 5fc4cc49bf52d4743518a7090c330968f1fdaa62 Mon Sep 17 00:00:00 2001 From: johannkarlsson Date: Fri, 8 Jul 2022 11:45:11 +0000 Subject: [PATCH 2/7] Sonos store last radio url --- queries/sonos.py | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/queries/sonos.py b/queries/sonos.py index 15ea25d2..a9b13943 100644 --- a/queries/sonos.py +++ b/queries/sonos.py @@ -377,12 +377,17 @@ def _create_or_join_session(self): ------------------------------------- PUBLIC METHODS -------------------------------------------------------------------------------- """ - def play_radio_stream(self, radio_url): #: Optional[str] = self._device_data.get] + def play_radio_stream(self, radio_url): #: Optional[str] = self._device_data.get] print("play radio stream") session_id = self._create_or_join_session() + if radio_url is None: + try: + radio_url = self._device_data["sonos"]["data"]["last_radio_url"] + except KeyError: + radio_url = "http://netradio.ruv.is/rondo.mp3" url = f"https://api.ws.sonos.com/control/api/v1//playbackSessions/{session_id}/playbackSession/loadStreamUrl?" - + print("RADIO URL :", radio_url) payload = json.dumps( { "streamUrl": f"{radio_url}", @@ -399,6 +404,8 @@ def play_radio_stream(self, radio_url): #: Optional[str] = self._device_data.get response = post_to_json_api(url, payload, headers) if response is None: return "Group not found" + data_dict = {"sonos": {"data": {"last_radio_url": radio_url}}} + self._store_data(data_dict) print(response.get("text")) def increase_volume(self): From d73dc29bad376e3a9d485b68bcfda88c09211c68 Mon Sep 17 00:00:00 2001 From: hrolfurinn <106666932+hrolfurinn@users.noreply.github.com> Date: Fri, 8 Jul 2022 11:51:37 +0000 Subject: [PATCH 3/7] Added fast forward and rewind grammar also fixed some hotword issues as a result --- queries/grammars/iot_hue.grammar | 15 +- queries/grammars/iot_speakers.grammar | 34 +- queries/iot_hue.py | 625 +++++++++++++------------- queries/iot_speakers.py | 22 +- 4 files changed, 373 insertions(+), 323 deletions(-) diff --git a/queries/grammars/iot_hue.grammar b/queries/grammars/iot_hue.grammar index 56656c10..2466e5e2 100644 --- a/queries/grammars/iot_hue.grammar +++ b/queries/grammars/iot_hue.grammar @@ -186,17 +186,20 @@ QIoTLocationPrepositionSecondPart -> "á" | "í" QIoTGroupName/fall -> - no/fall + QIoTLightsBanwords/fall + > no/fall QIoTLightName/fall -> - no/fall + QIoTLightsBanwords/fall + > no/fall QIoTColorName -> {color_names} QIoTSceneName -> - no - | lo + QIoTLightsBanwords/fall + > no + > lo QIoTAnnadAndlag -> QIoTNewSetting/nf @@ -320,5 +323,5 @@ QIoTSettingWord/fall -> 'stilling'/fall # Catching hotwords from iot_speakers -QIoTLightsBanwords -> - QIoTSpeakerHotwords/nf \ No newline at end of file +QIoTLightsBanwords/fall -> + QIoTSpeakerHotwords/fall \ No newline at end of file diff --git a/queries/grammars/iot_speakers.grammar b/queries/grammars/iot_speakers.grammar index 611d59de..bf6cb58b 100644 --- a/queries/grammars/iot_speakers.grammar +++ b/queries/grammars/iot_speakers.grammar @@ -12,6 +12,7 @@ Query → QIoTSpeaker → QIoTSpeakerQuery +# TODO: Flesh out skip queries QIoTSpeakerQuery → QIoTSpeakerMakeVerb QIoTSpeakerMakeRest | QIoTSpeakerSetVerb QIoTSpeakerSetRest @@ -19,7 +20,8 @@ QIoTSpeakerQuery → | QIoTSpeakerTurnOnOrOffVerb QIoTSpeakerTurnOrOffOnRest | QIoTSpeakerPlayOrPauseVerb QIoTSpeakerPlayOrPauseRest | QIoTSpeakerIncreaseOrDecreaseVerb QIoTSpeakerIncreaseOrDecreaseRest - | QIoTSpeakerRadioStationName + | QIoTSpeakerSkipVerb + | QIoTSpeakerNewSetting/fall QIoTSpeakerMakeVerb → 'gera:so'_bh @@ -71,6 +73,9 @@ QIoTSpeakerDecreaseVerb → 'lækka:so'_bh | 'minnka:so'_bh +QIoTSpeakerSkipVerb -> + 'skippa:so'_bh + QIoTSpeakerMakeRest → QIoTSpeakerMusicOrSoundPhrase/þf QIoTSpeakerComparative/nf QIoTSpeakerHvar | QIoTSpeakerMusicOrSoundPhrase/þf QIoTSpeakerHvar? QIoTSpeakerComparative/nf @@ -93,7 +98,8 @@ QIoTSpeakerTurnOrOffOnRest → QIoTSpeakerPlayOrPauseRest → QIoTSpeakerMusicWord/þf QIoTSpeakerHvarWithSpeaker? - | QIoTSpeakerNewRadio/þf? QIoTSpeakerHvarWithSpeaker? + | QIoTSpeakerNewRadio/þf QIoTSpeakerHvarWithSpeaker? + | QIoTSpeakerNewNextOrPrevious/þf QIoTSpeakerHvarWithSpeaker? QIoTSpeakerIncreaseOrDecreaseRest → QIoTSpeakerMusicOrSoundPhrase/þf QIoTSpeakerHvar? @@ -113,15 +119,20 @@ QIoTSpeakerAHverju → "á" QIoTSpeakerMusicOrApplianceWord/þgf | "á" QIoTSpeakerNewRadio/þgf | "á" QIoTSpeakerMusicOrRadioWord/þgf "í" QIoTSpeakerSpeakerWord/þgf + | "á" QIoTSpeakerNewNextOrPrevious/fall QIoTSpeakerNewSetting/fall → QIoTSpeakerNewRadio/fall - | QIoTSpeakerNewPlay/fall - | QIoTSpeakerNewPause/fall + | QIoTSpeakerNewPlayOrPause/fall + | QIoTSpeakerNewNextOrPrevious/fall QIoTSpeakerNewRadio/fall → QIoTSpeakerRadioStationWord/fall? QIoTSpeakerRadioStationName +QIoTSpeakerNewPlayOrPause/fall -> + QIoTSpeakerNewPlay/fall + | QIoTSpeakerNewPause/fall + QIoTSpeakerNewPlay/fall → "play" | "plei" @@ -131,6 +142,17 @@ QIoTSpeakerNewPause/fall → 'pása'/fall | 'stopp'/fall +QIoTSpeakerNewNextOrPrevious/fall -> + QIoTSpeakerNewNext/fall + | QIoTSpeakerNewPrevious/fall + +QIoTSpeakerNewNext/fall -> + 'næstur:lo'_kvk/fall 'lag:hk'_et/fall + +QIoTSpeakerNewPrevious/fall -> + 'seinastur:lo'_kvk/fall 'lag:hk'_et/fall + | 'síðastur:lo'_kvk/fall 'lag:hk'_et/fall + QIoTSpeakerMusicOrSoundPhrase/fall → QIoTSpeakerMusicPhrase/fall | QIoTSpeakerSoundPhrase/fall @@ -437,8 +459,10 @@ QIoTSpeaker90s → "næntís" | "nineties" +# TODO: Fix the song hotword # Hotwords to block other similarly phrased query modules from catching queries belonging to iot_speakers QIoTSpeakerHotwords/fall -> QIoTSpeakerMusicOrApplianceWord/fall | QIoTSpeakerSoundWord/fall - | QIoTSpeakerRadioStationName \ No newline at end of file + | QIoTSpeakerRadioStationName + | 'lag:no' \ No newline at end of file diff --git a/queries/iot_hue.py b/queries/iot_hue.py index ae644111..f9553680 100755 --- a/queries/iot_hue.py +++ b/queries/iot_hue.py @@ -1,266 +1,267 @@ -# """ - -# Greynir: Natural language processing for Icelandic - -# Randomness query response module - -# Copyright (C) 2022 Miðeind ehf. - -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. - -# You should have received a copy of the GNU General Public License -# along with this program. If not, see http://www.gnu.org/licenses/. - -# This query module handles queries related to the generation -# of random numbers, e.g. "Kastaðu tengingi", "Nefndu tölu milli 5 og 10", etc. - -# """ - -# # TODO: add "láttu", "hafðu", "litaðu", "kveiktu" functionality. -# # TODO: make the objects of sentences more modular, so that the same structure doesn't need to be written for each action -# # TODO: ditto the previous comment. make the initial non-terminals general and go into specifics at the terminal level instead. -# # TODO: substituion klósett, baðherbergi hugmyndÆ senda lista i javascript og profa i röð -# # TODO: Embla stores old javascript code cached which has caused errors -# # TODO: Cut down javascript sent to Embla -# # TODO: Two specified groups or lights. -# # TODO: No specified location -# # TODO: Fix scene issues -# # TODO: Turning on lights without using "turn on" -# # TODO: Add functionality for robot-like commands "ljós í eldhúsinu", "rauður í eldhúsinu" - -# from typing import Dict, Mapping, Optional, cast, FrozenSet -# from typing_extensions import TypedDict - -# import logging -# import random -# import json -# import flask - -# from reynir.lemmatize import simple_lemmatize - -# from query import Query, QueryStateDict, AnswerTuple -# from queries import gen_answer, read_jsfile, read_grammar_file -# from tree import Result, Node, TerminalNode - - -# class SmartLights(TypedDict): -# selected_light: str -# philips_hue: Dict[str, str] - - -# class DeviceData(TypedDict): -# smartlights: SmartLights - - -# _IoT_QTYPE = "IoT" - -# TOPIC_LEMMAS = [ -# "ljós", -# "kveikja", -# "litur", -# "birta", -# "hækka", -# "stemmning", -# "sena", -# "stemming", -# "stemning", -# ] - - -# def help_text(lemma: str) -> str: -# """Help text to return when query.py is unable to parse a query but -# one of the above lemmas is found in it""" -# return "Ég skil þig ef þú segir til dæmis: {0}.".format( -# random.choice( -# ( -# "Kveiktu á ljósunum inni í eldhúsi", -# "Slökktu á leslampanum", -# "Breyttu lit lýsingarinnar í stofunni í bláan", -# "Gerðu ljósið í borðstofunni bjartara", -# "Stilltu á bjartasta niðri í kjallara", -# ) -# ) -# ) +""" + + Greynir: Natural language processing for Icelandic + + Randomness query response module + + Copyright (C) 2022 Miðeind ehf. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see http://www.gnu.org/licenses/. + This query module handles queries related to the generation + of random numbers, e.g. "Kastaðu tengingi", "Nefndu tölu milli 5 og 10", etc. -# _COLORS = { -# "gulur": 60 * 65535 / 360, -# "rauður": 360 * 65535 / 360, -# "grænn": 120 * 65535 / 360, -# "blár": 240 * 65535 / 360, -# "ljósblár": 180 * 65535 / 360, -# "bleikur": 300 * 65535 / 360, -# "hvítur": [], -# "fjólublár": [], -# "brúnn": [], -# "appelsínugulur": [], -# } +""" +# TODO: add "láttu", "hafðu", "litaðu", "kveiktu" functionality. +# TODO: make the objects of sentences more modular, so that the same structure doesn't need to be written for each action +# TODO: ditto the previous comment. make the initial non-terminals general and go into specifics at the terminal level instead. +# TODO: substituion klósett, baðherbergi hugmyndÆ senda lista i javascript og profa i röð +# TODO: Embla stores old javascript code cached which has caused errors +# TODO: Cut down javascript sent to Embla +# TODO: Two specified groups or lights. +# TODO: No specified location +# TODO: Fix scene issues +# TODO: Turning on lights without using "turn on" +# TODO: Add functionality for robot-like commands "ljós í eldhúsinu", "rauður í eldhúsinu" -# # This module wants to handle parse trees for queries -# HANDLE_TREE = True +from typing import Dict, Mapping, Optional, cast, FrozenSet +from typing_extensions import TypedDict -# # The grammar nonterminals this module wants to handle -# QUERY_NONTERMINALS = {"QIoT"} +import logging +import random +import json +import flask -# # The context-free grammar for the queries recognized by this plug-in module -# # GRAMMAR = read_grammar_file("iot_hue") +from reynir.lemmatize import simple_lemmatize -# GRAMMAR = read_grammar_file( -# "iot_hue", color_names=" | ".join(f"'{color}:lo'" for color in _COLORS.keys()) -# ) +from query import Query, QueryStateDict, AnswerTuple +from queries import gen_answer, read_jsfile, read_grammar_file +from tree import Result, Node, TerminalNode -# def QIoTQuery(node: Node, params: QueryStateDict, result: Result) -> None: -# result.qtype = _IoT_QTYPE +class SmartLights(TypedDict): + selected_light: str + philips_hue: Dict[str, str] -# def QIoTColorWord(node: Node, params: QueryStateDict, result: Result) -> None: -# result.changing_color = True +class DeviceData(TypedDict): + smartlights: SmartLights -# def QIoTSceneWord(node: Node, params: QueryStateDict, result: Result) -> None: -# result.changing_scene = True +_IoT_QTYPE = "IoT" -# def QIoTBrightnessWord(node: Node, params: QueryStateDict, result: Result) -> None: -# result.changing_brightness = True +TOPIC_LEMMAS = [ + "ljós", + "kveikja", + "litur", + "birta", + "hækka", + "stemmning", + "sena", + "stemming", + "stemning", +] +def help_text(lemma: str) -> str: + """Help text to return when query.py is unable to parse a query but + one of the above lemmas is found in it""" + return "Ég skil þig ef þú segir til dæmis: {0}.".format( + random.choice( + ( + "Kveiktu á ljósunum inni í eldhúsi", + "Slökktu á leslampanum", + "Breyttu lit lýsingarinnar í stofunni í bláan", + "Gerðu ljósið í borðstofunni bjartara", + "Stilltu á bjartasta niðri í kjallara", + ) + ) + ) -# def QIoTTurnOnLightsRest(node: Node, params: QueryStateDict, result: Result) -> None: -# result.action = "turn_on" -# if "hue_obj" not in result: -# result["hue_obj"] = {"on": True} -# else: -# result["hue_obj"]["on"] = True +_COLORS = { + "gulur": 60 * 65535 / 360, + "rauður": 360 * 65535 / 360, + "grænn": 120 * 65535 / 360, + "blár": 240 * 65535 / 360, + "ljósblár": 180 * 65535 / 360, + "bleikur": 300 * 65535 / 360, + "hvítur": [], + "fjólublár": [], + "brúnn": [], + "appelsínugulur": [], +} -# def QIoTTurnOffLightsRest(node: Node, params: QueryStateDict, result: Result) -> None: -# result.action = "turn_off" -# if "hue_obj" not in result: -# result["hue_obj"] = {"on": False} -# else: -# result["hue_obj"]["on"] = False +# This module wants to handle parse trees for queries +HANDLE_TREE = True -# def QIoTNewColor(node: Node, params: QueryStateDict, result: Result) -> None: -# result.action = "set_color" -# print(result.color_name) -# color_hue = _COLORS.get(result.color_name, None) -# print(color_hue) -# if color_hue is not None: -# if "hue_obj" not in result: -# result["hue_obj"] = {"on": True, "hue": int(color_hue)} -# else: -# result["hue_obj"]["hue"] = int(color_hue) -# result["hue_obj"]["on"] = True +# The grammar nonterminals this module wants to handle +QUERY_NONTERMINALS = {"QIoT"} +# The context-free grammar for the queries recognized by this plug-in module +# GRAMMAR = read_grammar_file("iot_hue") -# def QIoTMoreBrighterOrHigher( -# node: Node, params: QueryStateDict, result: Result -# ) -> None: -# result.action = "increase_brightness" -# if "hue_obj" not in result: -# result["hue_obj"] = {"on": True, "bri_inc": 64} -# else: -# result["hue_obj"]["bri_inc"] = 64 -# result["hue_obj"]["on"] = True +GRAMMAR = read_grammar_file( + "iot_hue", color_names=" | ".join(f"'{color}:lo'" for color in _COLORS.keys()) +) -# def QIoTLessDarkerOrLower(node: Node, params: QueryStateDict, result: Result) -> None: -# result.action = "decrease_brightness" -# if "hue_obj" not in result: -# result["hue_obj"] = {"bri_inc": -64} -# else: -# result["hue_obj"]["bri_inc"] = -64 +def QIoTQuery(node: Node, params: QueryStateDict, result: Result) -> None: + result.qtype = _IoT_QTYPE -# def QIoTIncreaseVerb(node: Node, params: QueryStateDict, result: Result) -> None: -# result.action = "increase_brightness" -# if "hue_obj" not in result: -# result["hue_obj"] = {"on": True, "bri_inc": 64} -# else: -# result["hue_obj"]["bri_inc"] = 64 -# result["hue_obj"]["on"] = True +def QIoTColorWord(node: Node, params: QueryStateDict, result: Result) -> None: + result.changing_color = True + + +def QIoTSceneWord(node: Node, params: QueryStateDict, result: Result) -> None: + result.changing_scene = True + +def QIoTBrightnessWord(node: Node, params: QueryStateDict, result: Result) -> None: + result.changing_brightness = True -# def QIoTDecreaseVerb(node: Node, params: QueryStateDict, result: Result) -> None: -# result.action = "decrease_brightness" -# if "hue_obj" not in result: -# result["hue_obj"] = {"bri_inc": -64} -# else: -# result["hue_obj"]["bri_inc"] = -64 +def QIoTTurnOnLightsRest(node: Node, params: QueryStateDict, result: Result) -> None: + result.action = "turn_on" + if "hue_obj" not in result: + result["hue_obj"] = {"on": True} + else: + result["hue_obj"]["on"] = True -# def QIoTBrightest(node: Node, params: QueryStateDict, result: Result) -> None: -# result.action = "decrease_brightness" -# if "hue_obj" not in result: -# result["hue_obj"] = {"bri": 255} -# else: -# result["hue_obj"]["bri"] = 255 +def QIoTTurnOffLightsRest(node: Node, params: QueryStateDict, result: Result) -> None: + result.action = "turn_off" + if "hue_obj" not in result: + result["hue_obj"] = {"on": False} + else: + result["hue_obj"]["on"] = False -# def QIoTDarkest(node: Node, params: QueryStateDict, result: Result) -> None: -# result.action = "decrease_brightness" -# if "hue_obj" not in result: -# result["hue_obj"] = {"bri": 0} -# else: -# result["hue_obj"]["bri"] = 0 + +def QIoTNewColor(node: Node, params: QueryStateDict, result: Result) -> None: + result.action = "set_color" + print(result.color_name) + color_hue = _COLORS.get(result.color_name, None) + print(color_hue) + if color_hue is not None: + if "hue_obj" not in result: + result["hue_obj"] = {"on": True, "hue": int(color_hue)} + else: + result["hue_obj"]["hue"] = int(color_hue) + result["hue_obj"]["on"] = True -# def QIoTNewScene(node: Node, params: QueryStateDict, result: Result) -> None: -# result.action = "set_scene" -# scene_name = result.get("scene_name", None) -# print("scene: " + scene_name) -# if scene_name is not None: -# if "hue_obj" not in result: -# result["hue_obj"] = {"on": True, "scene": scene_name} -# else: -# result["hue_obj"]["scene"] = scene_name -# result["hue_obj"]["on"] = True - - -# def QIoTColorName(node: Node, params: QueryStateDict, result: Result) -> None: -# result["color_name"] = ( -# node.first_child(lambda x: True).string_self().strip("'").split(":")[0] -# ) +def QIoTMoreBrighterOrHigher( + node: Node, params: QueryStateDict, result: Result +) -> None: + result.action = "increase_brightness" + if "hue_obj" not in result: + result["hue_obj"] = {"on": True, "bri_inc": 64} + else: + result["hue_obj"]["bri_inc"] = 64 + result["hue_obj"]["on"] = True + + +def QIoTLessDarkerOrLower(node: Node, params: QueryStateDict, result: Result) -> None: + result.action = "decrease_brightness" + if "hue_obj" not in result: + result["hue_obj"] = {"bri_inc": -64} + else: + result["hue_obj"]["bri_inc"] = -64 + + +def QIoTIncreaseVerb(node: Node, params: QueryStateDict, result: Result) -> None: + result.action = "increase_brightness" + if "hue_obj" not in result: + result["hue_obj"] = {"on": True, "bri_inc": 64} + else: + result["hue_obj"]["bri_inc"] = 64 + result["hue_obj"]["on"] = True + + +def QIoTDecreaseVerb(node: Node, params: QueryStateDict, result: Result) -> None: + result.action = "decrease_brightness" + if "hue_obj" not in result: + result["hue_obj"] = {"bri_inc": -64} + else: + result["hue_obj"]["bri_inc"] = -64 + + +def QIoTBrightest(node: Node, params: QueryStateDict, result: Result) -> None: + result.action = "decrease_brightness" + if "hue_obj" not in result: + result["hue_obj"] = {"bri": 255} + else: + result["hue_obj"]["bri"] = 255 + + +def QIoTDarkest(node: Node, params: QueryStateDict, result: Result) -> None: + result.action = "decrease_brightness" + if "hue_obj" not in result: + result["hue_obj"] = {"bri": 0} + else: + result["hue_obj"]["bri"] = 0 + + +def QIoTNewScene(node: Node, params: QueryStateDict, result: Result) -> None: + result.action = "set_scene" + scene_name = result.get("scene_name", None) + print("scene: " + scene_name) + if scene_name is not None: + if "hue_obj" not in result: + result["hue_obj"] = {"on": True, "scene": scene_name} + else: + result["hue_obj"]["scene"] = scene_name + result["hue_obj"]["on"] = True + +def QIoTColorName(node: Node, params: QueryStateDict, result: Result) -> None: + result["color_name"] = ( + node.first_child(lambda x: True).string_self().strip("'").split(":")[0] + ) -# def QIoTSceneName(node: Node, params: QueryStateDict, result: Result) -> None: -# result["scene_name"] = result._indefinite -# print("scene: " + result.get("scene_name", None)) +def QIoTSceneName(node: Node, params: QueryStateDict, result: Result) -> None: + result["scene_name"] = result._indefinite + print("scene: " + result.get("scene_name", None)) -# def QIoTGroupName(node: Node, params: QueryStateDict, result: Result) -> None: -# result["group_name"] = result._indefinite +def QIoTGroupName(node: Node, params: QueryStateDict, result: Result) -> None: + result["group_name"] = result._indefinite -# def QIoTLightName(node: Node, params: QueryStateDict, result: Result) -> None: -# result["light_name"] = result._indefinite +def QIoTLightName(node: Node, params: QueryStateDict, result: Result) -> None: + result["light_name"] = result._indefinite -# def QIoTLightsBanwords(node: Node, params: QueryStateDict, result: Result) -> None: -# result.abort = True +def QIoTSpeakerHotwords(node: Node, params: QueryStateDict, result: Result) -> None: + print("lights banwords") + result.abort = True -# # Convert color name into hue -# # Taken from home.py -# _COLOR_NAME_TO_CIE: Mapping[str, float] = { -# "gulur": 60 * 65535 / 360, -# "grænn": 120 * 65535 / 360, -# "ljósblár": 180 * 65535 / 360, -# "blár": 240 * 65535 / 360, -# "bleikur": 300 * 65535 / 360, -# "rauður": 360 * 65535 / 360, -# # "Rauð": 360 * 65535 / 360, -# } + +# Convert color name into hue +# Taken from home.py +_COLOR_NAME_TO_CIE: Mapping[str, float] = { + "gulur": 60 * 65535 / 360, + "grænn": 120 * 65535 / 360, + "ljósblár": 180 * 65535 / 360, + "blár": 240 * 65535 / 360, + "bleikur": 300 * 65535 / 360, + "rauður": 360 * 65535 / 360, + # "Rauð": 360 * 65535 / 360, +} # _SPEAKER_WORDS: FrozenSet[str] = frozenset( # ( @@ -305,96 +306,98 @@ # ) -# def sentence(state: QueryStateDict, result: Result) -> None: -# """Called when sentence processing is complete""" -# q: Query = state["query"] -# if result.get("abort"): -# q.set_error("E_QUERY_NOT_UNDERSTOOD") -# # lemmas = set( -# # i[0].root(state, result.params) -# # for i in result.enum_descendants(lambda x: isinstance(x, TerminalNode)) -# # ) -# # if not _SPEAKER_WORDS.isdisjoint(lemmas): -# # print("matched with music word list") -# # q.set_error("E_QUERY_NOT_UNDERSTOOD") -# # return -# changing_color = result.get("changing_color", False) -# changing_scene = result.get("changing_scene", False) -# changing_brightness = result.get("changing_brightness", False) -# print("error?", sum((changing_color, changing_scene, changing_brightness)) > 1) -# if ( -# sum((changing_color, changing_scene, changing_brightness)) > 1 -# or "qtype" not in result -# ): -# q.set_error("E_QUERY_NOT_UNDERSTOOD") -# return - -# q.set_qtype(result.qtype) - -# smartdevice_type = "iot_lights" -# client_id = str(q.client_id) -# print("client_id:", client_id) - -# # Fetch relevant data from the device_data table to perform an action on the lights -# device_data = cast(Optional[DeviceData], q.client_data(smartdevice_type)) -# print("location :", q.location) -# print("device data :", device_data) - -# selected_light: Optional[str] = None -# print("selected light:", selected_light) -# hue_credentials: Optional[Dict[str, str]] = None - -# if device_data is not None: -# dev = device_data -# assert dev is not None -# light = dev.get("philips_hue") -# hue_credentials = light.get("credentials") -# bridge_ip = hue_credentials.get("ip_address") -# username = hue_credentials.get("username") - -# if not device_data or not hue_credentials: -# answer = "Það vantar að tengja Philips Hub-inn." -# q.set_answer(*gen_answer(answer)) -# return - -# # Successfully matched a query type -# print("bridge_ip: ", bridge_ip) -# print("username: ", username) -# print("selected light :", selected_light) -# print("hue credentials :", hue_credentials) - -# try: -# # kalla í javascripts stuff -# light_or_group_name = result.get("light_name", result.get("group_name", "")) -# color_name = result.get("color_name", "") -# print("GROUP NAME:", light_or_group_name) -# print("COLOR NAME:", color_name) -# print(result.hue_obj) -# q.set_answer( -# *gen_answer( -# "ég var að kveikja ljósin! " -# # + group_name -# # + " " -# # + color_name -# # + " " -# # + result.action -# # + " " -# # + str(result.hue_obj.get("hue", "enginn litur")) -# ) -# ) -# js = ( -# read_jsfile("IoT_Embla/fuse.js") -# + f"var BRIDGE_IP = '{bridge_ip}';var USERNAME = '{username}';" -# + read_jsfile("IoT_Embla/Philips_Hue/fuse_search.js") -# + read_jsfile("IoT_Embla/Philips_Hue/lights.js") -# + read_jsfile("IoT_Embla/Philips_Hue/set_lights.js") -# ) -# js += f"setLights('{light_or_group_name}', '{json.dumps(result.hue_obj)}');" -# q.set_command(js) -# except Exception as e: -# logging.warning("Exception while processing random query: {0}".format(e)) -# q.set_error("E_EXCEPTION: {0}".format(e)) -# raise - - -# # f"var BRIDGE_IP = '192.168.1.68';var USERNAME = 'p3obluiXT13IbHMpp4X63ZvZnpNRdbqqMt723gy2';" +def sentence(state: QueryStateDict, result: Result) -> None: + """Called when sentence processing is complete""" + q: Query = state["query"] + print("start of sentence") + if result.get("abort"): + print("aborted") + q.set_error("E_QUERY_NOT_UNDERSTOOD") + # lemmas = set( + # i[0].root(state, result.params) + # for i in result.enum_descendants(lambda x: isinstance(x, TerminalNode)) + # ) + # if not _SPEAKER_WORDS.isdisjoint(lemmas): + # print("matched with music word list") + # q.set_error("E_QUERY_NOT_UNDERSTOOD") + # return + changing_color = result.get("changing_color", False) + changing_scene = result.get("changing_scene", False) + changing_brightness = result.get("changing_brightness", False) + print("error?", sum((changing_color, changing_scene, changing_brightness)) > 1) + if ( + sum((changing_color, changing_scene, changing_brightness)) > 1 + or "qtype" not in result + ): + q.set_error("E_QUERY_NOT_UNDERSTOOD") + return + + q.set_qtype(result.qtype) + + smartdevice_type = "iot_lights" + client_id = str(q.client_id) + print("client_id:", client_id) + + # Fetch relevant data from the device_data table to perform an action on the lights + device_data = cast(Optional[DeviceData], q.client_data(smartdevice_type)) + print("location :", q.location) + print("device data :", device_data) + + selected_light: Optional[str] = None + print("selected light:", selected_light) + hue_credentials: Optional[Dict[str, str]] = None + + if device_data is not None: + dev = device_data + assert dev is not None + light = dev.get("philips_hue") + hue_credentials = light.get("credentials") + bridge_ip = hue_credentials.get("ip_address") + username = hue_credentials.get("username") + + if not device_data or not hue_credentials: + answer = "Það vantar að tengja Philips Hub-inn." + q.set_answer(*gen_answer(answer)) + return + + # Successfully matched a query type + print("bridge_ip: ", bridge_ip) + print("username: ", username) + print("selected light :", selected_light) + print("hue credentials :", hue_credentials) + + try: + # kalla í javascripts stuff + light_or_group_name = result.get("light_name", result.get("group_name", "")) + color_name = result.get("color_name", "") + print("GROUP NAME:", light_or_group_name) + print("COLOR NAME:", color_name) + print(result.hue_obj) + q.set_answer( + *gen_answer( + "ég var að kveikja ljósin! " + # + group_name + # + " " + # + color_name + # + " " + # + result.action + # + " " + # + str(result.hue_obj.get("hue", "enginn litur")) + ) + ) + js = ( + read_jsfile("IoT_Embla/fuse.js") + + f"var BRIDGE_IP = '{bridge_ip}';var USERNAME = '{username}';" + + read_jsfile("IoT_Embla/Philips_Hue/fuse_search.js") + + read_jsfile("IoT_Embla/Philips_Hue/lights.js") + + read_jsfile("IoT_Embla/Philips_Hue/set_lights.js") + ) + js += f"setLights('{light_or_group_name}', '{json.dumps(result.hue_obj)}');" + q.set_command(js) + except Exception as e: + logging.warning("Exception while processing random query: {0}".format(e)) + q.set_error("E_EXCEPTION: {0}".format(e)) + raise + + +# f"var BRIDGE_IP = '192.168.1.68';var USERNAME = 'p3obluiXT13IbHMpp4X63ZvZnpNRdbqqMt723gy2';" diff --git a/queries/iot_speakers.py b/queries/iot_speakers.py index 3735345e..55c7f6b3 100644 --- a/queries/iot_speakers.py +++ b/queries/iot_speakers.py @@ -129,6 +129,26 @@ def QIoTSpeakerPauseVerb(node: Node, params: QueryStateDict, result: Result) -> result.qkey = "turn_off" +def QIoTSpeakerSkipVerb(node: Node, params: QueryStateDict, result: Result) -> None: + result.qkey = "fast_forward" + + +def QIoTSpeakerNewPlay(node: Node, params: QueryStateDict, result: Result) -> None: + result.qkey = "turn_on" + + +def QIoTSpeakerNewPause(node: Node, params: QueryStateDict, result: Result) -> None: + result.qkey = "turn_off" + + +def QIoTSpeakerNewNext(node: Node, params: QueryStateDict, result: Result) -> None: + result.qkey = "fast_forward" + + +def QIoTSpeakerNewPrevious(node: Node, params: QueryStateDict, result: Result) -> None: + result.qkey = "rewind" + + def QIoTSpeakerIncreaseVerb(node: Node, params: QueryStateDict, result: Result) -> None: result.qkey = "increase_volume" @@ -281,7 +301,7 @@ def sentence(state: QueryStateDict, result: Result) -> None: q: Query = state["query"] if "qkey" not in result: result.qkey = "turn_on" - if result.qkey == "turn_on" and result.target == "radio": + if result.qkey == "turn_on" and result.get("target") == "radio": result.qkey = "radio" if "qtype" in result: print("IF QTYPE AND QKEY") From deb0ec85646769beaa65701831205185774aaa38 Mon Sep 17 00:00:00 2001 From: johannkarlsson Date: Fri, 8 Jul 2022 11:55:36 +0000 Subject: [PATCH 4/7] Next prev song in iot_speakers --- queries/iot_speakers.py | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/queries/iot_speakers.py b/queries/iot_speakers.py index 55c7f6b3..7f965388 100644 --- a/queries/iot_speakers.py +++ b/queries/iot_speakers.py @@ -130,7 +130,7 @@ def QIoTSpeakerPauseVerb(node: Node, params: QueryStateDict, result: Result) -> def QIoTSpeakerSkipVerb(node: Node, params: QueryStateDict, result: Result) -> None: - result.qkey = "fast_forward" + result.qkey = "next_song" def QIoTSpeakerNewPlay(node: Node, params: QueryStateDict, result: Result) -> None: @@ -142,11 +142,11 @@ def QIoTSpeakerNewPause(node: Node, params: QueryStateDict, result: Result) -> N def QIoTSpeakerNewNext(node: Node, params: QueryStateDict, result: Result) -> None: - result.qkey = "fast_forward" + result.qkey = "next_song" def QIoTSpeakerNewPrevious(node: Node, params: QueryStateDict, result: Result) -> None: - result.qkey = "rewind" + result.qkey = "prev_song" def QIoTSpeakerIncreaseVerb(node: Node, params: QueryStateDict, result: Result) -> None: @@ -342,6 +342,16 @@ def sentence(state: QueryStateDict, result: Result) -> None: [radio_url], "Ég setti á útvarpstöðina", ], + "next_song": [ + sonos_client.next_song, + [], + "Ég hötta á næsta tón", + ], + "prev_song": [ + sonos_client.prev_song, + [], + "Ég hötta á fyrri tón", + ], } handler, args, answer = handler_map.get(result.qkey) response = handler(*args) From eaa2e45c4b4075771fe69d0aa786965fc0e4ce16 Mon Sep 17 00:00:00 2001 From: hrolfurinn <106666932+hrolfurinn@users.noreply.github.com> Date: Fri, 8 Jul 2022 13:04:53 +0000 Subject: [PATCH 5/7] minor fixes --- queries/grammars/iot_speakers.grammar | 12 +++++++----- queries/iot_hue.py | 1 + query.py | 1 + 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/queries/grammars/iot_speakers.grammar b/queries/grammars/iot_speakers.grammar index bf6cb58b..4cc705c7 100644 --- a/queries/grammars/iot_speakers.grammar +++ b/queries/grammars/iot_speakers.grammar @@ -1,7 +1,7 @@ # TODO: Fix music hardcoding # TODO: Check whether to force determinate form # TODO: "Settu á útvarpið", which station to play? -# TODO: Refactor make and let "Gerðu tónlistina hærri í hátalaranum (í eldhúsinu)"-type sentences +# TODO: "Kveiktu á tónlist í hátalarnum" /þgf = þgf /ef = ef @@ -112,13 +112,13 @@ QIoTSpeakerComparative/fall → # Sometimes "á" is not registered by Embla QIoTSpeakerAHvad → - "á"? QIoTSpeakerMusicOrRadioWord/þf - | "á"? QIoTSpeakerNewSetting/þf + "yfir"? "á"? QIoTSpeakerMusicOrRadioWord/þf + | "yfir"? "á"? QIoTSpeakerNewSetting/þf QIoTSpeakerAHverju → "á" QIoTSpeakerMusicOrApplianceWord/þgf | "á" QIoTSpeakerNewRadio/þgf - | "á" QIoTSpeakerMusicOrRadioWord/þgf "í" QIoTSpeakerSpeakerWord/þgf + | "á" QIoTSpeakerMusicOrRadioWord/þgf | "á" QIoTSpeakerNewNextOrPrevious/fall QIoTSpeakerNewSetting/fall → @@ -152,6 +152,7 @@ QIoTSpeakerNewNext/fall -> QIoTSpeakerNewPrevious/fall -> 'seinastur:lo'_kvk/fall 'lag:hk'_et/fall | 'síðastur:lo'_kvk/fall 'lag:hk'_et/fall + | 'fyrri:lo'_kvk/fall 'lag:hk'_et/fall QIoTSpeakerMusicOrSoundPhrase/fall → QIoTSpeakerMusicPhrase/fall @@ -465,4 +466,5 @@ QIoTSpeakerHotwords/fall -> QIoTSpeakerMusicOrApplianceWord/fall | QIoTSpeakerSoundWord/fall | QIoTSpeakerRadioStationName - | 'lag:no' \ No newline at end of file + | 'lag:no' + | QIoTSpeakerNewSetting/fall \ No newline at end of file diff --git a/queries/iot_hue.py b/queries/iot_hue.py index f9553680..e94bcbd3 100755 --- a/queries/iot_hue.py +++ b/queries/iot_hue.py @@ -313,6 +313,7 @@ def sentence(state: QueryStateDict, result: Result) -> None: if result.get("abort"): print("aborted") q.set_error("E_QUERY_NOT_UNDERSTOOD") + return # lemmas = set( # i[0].root(state, result.params) # for i in result.enum_descendants(lambda x: isinstance(x, TerminalNode)) diff --git a/query.py b/query.py index f598aaf7..e0391ee7 100755 --- a/query.py +++ b/query.py @@ -301,6 +301,7 @@ def process_queries( return False with self.context(session, processor, query=query) as state: for query_tree in self._query_trees: + print("Processing query tree", query_tree.string_self()) # Is the processor interested in the root nonterminal # of this query tree? if query_tree.string_self() in processor_query_types: From afec05ccf3be510f6c811b9df256070491e8d842 Mon Sep 17 00:00:00 2001 From: johannkarlsson Date: Fri, 8 Jul 2022 13:05:19 +0000 Subject: [PATCH 6/7] Next and prev song functionality in sonos client --- queries/iot_hue.py | 1 + queries/sonos.py | 69 ++++++++++++++++++++++++++++++---------------- 2 files changed, 47 insertions(+), 23 deletions(-) diff --git a/queries/iot_hue.py b/queries/iot_hue.py index f9553680..e94bcbd3 100755 --- a/queries/iot_hue.py +++ b/queries/iot_hue.py @@ -313,6 +313,7 @@ def sentence(state: QueryStateDict, result: Result) -> None: if result.get("abort"): print("aborted") q.set_error("E_QUERY_NOT_UNDERSTOOD") + return # lemmas = set( # i[0].root(state, result.params) # for i in result.enum_descendants(lambda x: isinstance(x, TerminalNode)) diff --git a/queries/sonos.py b/queries/sonos.py index a9b13943..0b8e3f49 100644 --- a/queries/sonos.py +++ b/queries/sonos.py @@ -78,7 +78,7 @@ from util import read_api_key from queries import query_json_api, post_to_json_api from query import Query -from typing import Dict, Optional +from typing import Dict import json @@ -114,6 +114,7 @@ def __init__( self._household_id = self._households[0]["id"] self._groups = self._get_groups() self._players = self._get_players() + self._group_id = self._get_group_id() self._store_sonos_data_and_credentials() """ @@ -359,8 +360,8 @@ def _create_playerdict_for_db(self, players: list): def _create_or_join_session(self): print("_create_or_join_session") - group_id = self._get_group_id() - url = f"https://api.ws.sonos.com/control/api/v1/groups/{group_id}/playbackSession/joinOrCreate" + # group_id = self._get_group_id() + url = f"https://api.ws.sonos.com/control/api/v1/groups/{self._group_id}/playbackSession/joinOrCreate" payload = json.dumps({"appId": "com.mideind.embla", "appContext": "embla123"}) headers = { @@ -410,8 +411,8 @@ def play_radio_stream(self, radio_url): #: Optional[str] = self._device_data.ge def increase_volume(self): print("increase_volume") - group_id = self._get_group_id() - url = f"https://api.ws.sonos.com/control/api/v1/groups/{group_id}/groupVolume/relative" + # group_id = self._get_group_id() + url = f"https://api.ws.sonos.com/control/api/v1/groups/{self._group_id}/groupVolume/relative" payload = json.dumps({"volumeDelta": 10}) headers = { @@ -445,9 +446,9 @@ def toggle_play(self): Toggles play/pause of a group """ print("toggle playpause") - group_id = self._get_group_id() + # group_id = self._get_group_id() print("exited group_id") - url = f"https://api.ws.sonos.com/control/api/v1/groups/{group_id}/playback/play" + url = f"https://api.ws.sonos.com/control/api/v1/groups/{self._group_id}/playback/play" headers = { "Content-Type": "application/json", "Authorization": f"Bearer {self._access_token}", @@ -466,11 +467,9 @@ def toggle_pause(self): Toggles play/pause of a group """ print("toggle playpause") - group_id = self._get_group_id() + # group_id = self._get_group_id() print("exited group_id") - url = ( - f"https://api.ws.sonos.com/control/api/v1/groups/{group_id}/playback/pause" - ) + url = f"https://api.ws.sonos.com/control/api/v1/groups/{self._group_id}/playback/pause" headers = { "Content-Type": "application/json", "Authorization": f"Bearer {self._access_token}", @@ -530,20 +529,44 @@ def play_chime(self): "Authorization": f"Bearer {self._access_token}", } - response = requests.request("POST", url, headers=headers, data=payload) + response = post_to_json_api(url, payload, headers) + + return response - print(response.text) + def next_song(self): + url = f"https://api.ws.sonos.com/control/api/v1/groups/{self._group_id}/playback/skipToNextTrack" - def _refresh_data(self, function): - print("refresh data") - print("device_data: ", self._device_data) - # self._device_data["sonos"]["data"] = None - # print("device_data after deletion: ", self._device_data) - self._households = self._get_households() - self._groups = self._get_groups() - self._players = self._get_players() - # self._store_sonos_data_and_credentials() - getattr(self, function)() + headers = { + "Content-Type": "application/json", + "Authorization": f"Bearer {self._access_token}", + } + + response = post_to_json_api(url, headers=headers) + + return response + + def prev_song(self): + url = f"https://api.ws.sonos.com/control/api/v1/groups/{self._group_id}/playback/skipToPreviousTrack" + + headers = { + "Content-Type": "application/json", + "Authorization": f"Bearer {self._access_token}", + } + + response = post_to_json_api(url, headers=headers) + + return response + + # def _refresh_data(self, function): + # print("refresh data") + # print("device_data: ", self._device_data) + # # self._device_data["sonos"]["data"] = None + # # print("device_data after deletion: ", self._device_data) + # self._households = self._get_households() + # self._groups = self._get_groups() + # self._players = self._get_players() + # # self._store_sonos_data_and_credentials() + # getattr(self, function)() # def get_groups_and_players(self): # """ From 69aa7d76885f1fd32e4cfc6be567249b16397a46 Mon Sep 17 00:00:00 2001 From: hrolfurinn <106666932+hrolfurinn@users.noreply.github.com> Date: Fri, 8 Jul 2022 14:01:02 +0000 Subject: [PATCH 7/7] moved banwords into sentence again --- queries/grammars/iot_hue.grammar | 18 ++--- queries/grammars/iot_speakers.grammar | 15 ++-- queries/iot_hue.py | 99 ++++++++++++++------------- query.py | 2 +- 4 files changed, 69 insertions(+), 65 deletions(-) diff --git a/queries/grammars/iot_hue.grammar b/queries/grammars/iot_hue.grammar index 2466e5e2..cd2ff734 100644 --- a/queries/grammars/iot_hue.grammar +++ b/queries/grammars/iot_hue.grammar @@ -186,20 +186,20 @@ QIoTLocationPrepositionSecondPart -> "á" | "í" QIoTGroupName/fall -> - QIoTLightsBanwords/fall - > no/fall + # QIoTLightsBanwords/fall + no/fall QIoTLightName/fall -> - QIoTLightsBanwords/fall - > no/fall + # QIoTLightsBanwords/fall + no/fall QIoTColorName -> {color_names} QIoTSceneName -> - QIoTLightsBanwords/fall - > no - > lo + # QIoTLightsBanwords/fall + no + | lo QIoTAnnadAndlag -> QIoTNewSetting/nf @@ -323,5 +323,5 @@ QIoTSettingWord/fall -> 'stilling'/fall # Catching hotwords from iot_speakers -QIoTLightsBanwords/fall -> - QIoTSpeakerHotwords/fall \ No newline at end of file +# QIoTLightsBanwords/fall -> +# QIoTSpeakerHotwords/fall \ No newline at end of file diff --git a/queries/grammars/iot_speakers.grammar b/queries/grammars/iot_speakers.grammar index 4cc705c7..172ac4b3 100644 --- a/queries/grammars/iot_speakers.grammar +++ b/queries/grammars/iot_speakers.grammar @@ -148,11 +148,14 @@ QIoTSpeakerNewNextOrPrevious/fall -> QIoTSpeakerNewNext/fall -> 'næstur:lo'_kvk/fall 'lag:hk'_et/fall + | 'lag:hk'_et_gr/fall "á" "eftir" + # | "næsta" "lagið" QIoTSpeakerNewPrevious/fall -> 'seinastur:lo'_kvk/fall 'lag:hk'_et/fall | 'síðastur:lo'_kvk/fall 'lag:hk'_et/fall | 'fyrri:lo'_kvk/fall 'lag:hk'_et/fall + | 'lag:hk'_et_gr/fall "á" "undan" QIoTSpeakerMusicOrSoundPhrase/fall → QIoTSpeakerMusicPhrase/fall @@ -462,9 +465,9 @@ QIoTSpeaker90s → # TODO: Fix the song hotword # Hotwords to block other similarly phrased query modules from catching queries belonging to iot_speakers -QIoTSpeakerHotwords/fall -> - QIoTSpeakerMusicOrApplianceWord/fall - | QIoTSpeakerSoundWord/fall - | QIoTSpeakerRadioStationName - | 'lag:no' - | QIoTSpeakerNewSetting/fall \ No newline at end of file +# QIoTSpeakerHotwords/fall -> +# QIoTSpeakerMusicOrApplianceWord/fall +# | QIoTSpeakerSoundWord/fall +# | QIoTSpeakerRadioStationName +# | 'lag:no' +# | QIoTSpeakerNewSetting/fall \ No newline at end of file diff --git a/queries/iot_hue.py b/queries/iot_hue.py index e94bcbd3..a9c32965 100755 --- a/queries/iot_hue.py +++ b/queries/iot_hue.py @@ -263,47 +263,48 @@ def QIoTSpeakerHotwords(node: Node, params: QueryStateDict, result: Result) -> N # "Rauð": 360 * 65535 / 360, } -# _SPEAKER_WORDS: FrozenSet[str] = frozenset( -# ( -# "tónlist", -# "hátalari", -# "bylgja", -# "útvarp", -# "útvarpsstöð", -# "útvarp saga", -# "gullbylgja", -# "x-ið", -# "léttbylgjan", -# "rás 1", -# "rás 2", -# "rondo", -# "rondó", -# "fm 957", -# "fm957", -# "fm-957", -# "k-100", -# "k 100", -# "kk 100", -# "k hundrað", -# "kk hundrað", -# "x977", -# "x 977", -# "x-977", -# "x-ið 977", -# "x-ið", -# "retro", -# "kiss fm", -# "flassbakk", -# "flassbakk fm", -# "útvarp hundraðið", -# "útvarp 101", -# "útvarp hundraðogeinn", -# "útvarp hundrað og einn", -# "útvarp hundrað einn", -# "útvarp hundrað 1", -# "útvarp", -# ) -# ) +_SPEAKER_WORDS: FrozenSet[str] = frozenset( + ( + "tónlist", + "lag", + "hátalari", + "bylgja", + "útvarp", + "útvarpsstöð", + "útvarp saga", + "gullbylgja", + "x-ið", + "léttbylgjan", + "rás 1", + "rás 2", + "rondo", + "rondó", + "fm 957", + "fm957", + "fm-957", + "k-100", + "k 100", + "kk 100", + "k hundrað", + "kk hundrað", + "x977", + "x 977", + "x-977", + "x-ið 977", + "x-ið", + "retro", + "kiss fm", + "flassbakk", + "flassbakk fm", + "útvarp hundraðið", + "útvarp 101", + "útvarp hundraðogeinn", + "útvarp hundrað og einn", + "útvarp hundrað einn", + "útvarp hundrað 1", + "útvarp", + ) +) def sentence(state: QueryStateDict, result: Result) -> None: @@ -314,14 +315,14 @@ def sentence(state: QueryStateDict, result: Result) -> None: print("aborted") q.set_error("E_QUERY_NOT_UNDERSTOOD") return - # lemmas = set( - # i[0].root(state, result.params) - # for i in result.enum_descendants(lambda x: isinstance(x, TerminalNode)) - # ) - # if not _SPEAKER_WORDS.isdisjoint(lemmas): - # print("matched with music word list") - # q.set_error("E_QUERY_NOT_UNDERSTOOD") - # return + lemmas = set( + i[0].root(state, result.params) + for i in result.enum_descendants(lambda x: isinstance(x, TerminalNode)) + ) + if not _SPEAKER_WORDS.isdisjoint(lemmas): + print("matched with music word list") + q.set_error("E_QUERY_NOT_UNDERSTOOD") + return changing_color = result.get("changing_color", False) changing_scene = result.get("changing_scene", False) changing_brightness = result.get("changing_brightness", False) diff --git a/query.py b/query.py index e0391ee7..a6ebc91d 100755 --- a/query.py +++ b/query.py @@ -301,7 +301,7 @@ def process_queries( return False with self.context(session, processor, query=query) as state: for query_tree in self._query_trees: - print("Processing query tree", query_tree.string_self()) + print("Processing query tree", query_tree.string_self(), "in module", processor.__name__) # Is the processor interested in the root nonterminal # of this query tree? if query_tree.string_self() in processor_query_types: