Skip to content

Commit

Permalink
Merge pull request #45 from sultur/grammar3
Browse files Browse the repository at this point in the history
Grammar3
  • Loading branch information
johannkarlsson authored Jul 11, 2022
2 parents 2a99a74 + 077ccbc commit e655d8d
Show file tree
Hide file tree
Showing 6 changed files with 138 additions and 66 deletions.
7 changes: 5 additions & 2 deletions queries/grammars/iot_hue.grammar
Original file line number Diff line number Diff line change
Expand Up @@ -186,15 +186,18 @@ QIoTLocationPrepositionSecondPart ->
"á" | "í"

QIoTGroupName/fall ->
# QIoTLightsBanwords/fall
no/fall

QIoTLightName/fall ->
# QIoTLightsBanwords/fall
no/fall

QIoTColorName ->
{color_names}

QIoTSceneName ->
# QIoTLightsBanwords/fall
no
| lo

Expand Down Expand Up @@ -320,5 +323,5 @@ QIoTSettingWord/fall ->
'stilling'/fall

# Catching hotwords from iot_speakers
QIoTLightsBanwords ->
QIoTSpeakerHotwords/nf
# QIoTLightsBanwords/fall ->
# QIoTSpeakerHotwords/fall
53 changes: 41 additions & 12 deletions queries/grammars/iot_speakers.grammar
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -12,14 +12,16 @@ Query →
QIoTSpeaker →
QIoTSpeakerQuery

# TODO: Flesh out skip queries
QIoTSpeakerQuery →
QIoTSpeakerMakeVerb QIoTSpeakerMakeRest
| QIoTSpeakerSetVerb QIoTSpeakerSetRest
| QIoTSpeakerLetVerb QIoTSpeakerLetRest
| QIoTSpeakerTurnOnOrOffVerb QIoTSpeakerTurnOrOffOnRest
| QIoTSpeakerPlayOrPauseVerb QIoTSpeakerPlayOrPauseRest
| QIoTSpeakerIncreaseOrDecreaseVerb QIoTSpeakerIncreaseOrDecreaseRest
| QIoTSpeakerRadioStationName
| QIoTSpeakerSkipVerb
| QIoTSpeakerNewSetting/fall

QIoTSpeakerMakeVerb →
'gera:so'_bh
Expand Down Expand Up @@ -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
Expand All @@ -93,7 +98,8 @@ QIoTSpeakerTurnOrOffOnRest →

QIoTSpeakerPlayOrPauseRest →
QIoTSpeakerMusicWord/þf QIoTSpeakerHvarWithSpeaker?
| QIoTSpeakerNewRadio/þf? QIoTSpeakerHvarWithSpeaker?
| QIoTSpeakerNewRadio/þf QIoTSpeakerHvarWithSpeaker?
| QIoTSpeakerNewNextOrPrevious/þf QIoTSpeakerHvarWithSpeaker?

QIoTSpeakerIncreaseOrDecreaseRest →
QIoTSpeakerMusicOrSoundPhrase/þf QIoTSpeakerHvar?
Expand All @@ -106,22 +112,27 @@ 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 →
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"
Expand All @@ -131,6 +142,21 @@ QIoTSpeakerNewPause/fall →
'pása'/fall
| 'stopp'/fall

QIoTSpeakerNewNextOrPrevious/fall ->
QIoTSpeakerNewNext/fall
| QIoTSpeakerNewPrevious/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
| QIoTSpeakerSoundPhrase/fall
Expand Down Expand Up @@ -437,8 +463,11 @@ 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
# QIoTSpeakerHotwords/fall ->
# QIoTSpeakerMusicOrApplianceWord/fall
# | QIoTSpeakerSoundWord/fall
# | QIoTSpeakerRadioStationName
# | 'lag:no'
# | QIoTSpeakerNewSetting/fall
25 changes: 15 additions & 10 deletions queries/iot_hue.py
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@ def help_text(lemma: str) -> str:
"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

Expand All @@ -133,7 +134,6 @@ def QIoTBrightnessWord(node: Node, params: QueryStateDict, result: Result) -> No
result.changing_brightness = True



def QIoTTurnOnLightsRest(node: Node, params: QueryStateDict, result: Result) -> None:
result.action = "turn_on"
if "hue_obj" not in result:
Expand Down Expand Up @@ -246,7 +246,8 @@ def QIoTLightName(node: Node, params: QueryStateDict, result: Result) -> None:
result["light_name"] = result._indefinite


def QIoTLightsBanwords(node: Node, params: QueryStateDict, result: Result) -> None:
def QIoTSpeakerHotwords(node: Node, params: QueryStateDict, result: Result) -> None:
print("lights banwords")
result.abort = True


Expand All @@ -265,6 +266,7 @@ def QIoTLightsBanwords(node: Node, params: QueryStateDict, result: Result) -> No
_SPEAKER_WORDS: FrozenSet[str] = frozenset(
(
"tónlist",
"lag",
"hátalari",
"bylgja",
"útvarp",
Expand Down Expand Up @@ -308,16 +310,19 @@ def QIoTLightsBanwords(node: Node, params: QueryStateDict, result: Result) -> No
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")
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")
# 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
return
changing_color = result.get("changing_color", False)
changing_scene = result.get("changing_scene", False)
changing_brightness = result.get("changing_brightness", False)
Expand Down
101 changes: 64 additions & 37 deletions queries/iot_speakers.py
Original file line number Diff line number Diff line change
Expand Up @@ -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 = "next_song"


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 = "next_song"


def QIoTSpeakerNewPrevious(node: Node, params: QueryStateDict, result: Result) -> None:
result.qkey = "prev_song"


def QIoTSpeakerIncreaseVerb(node: Node, params: QueryStateDict, result: Result) -> None:
result.qkey = "increase_volume"

Expand Down Expand Up @@ -275,47 +295,15 @@ def QIoTSpeakerUtvarpSudurland(
result.station = "Útvarp Suðurland"


def QIoTSpeakerNext(node: Node, params: QueryStateDict, result: Result) -> None:
result["qkey"] = "next_song"


def QIoTSpeakerPrevious(node: Node, params: QueryStateDict, result: Result) -> None:
result["qkey"] = "prev_song"


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"],
"next_song": ["next_song", "Skal gert. Næsta lag."],
"prev_song": ["prev_song", "Skal gert. Fyrra lag."],
}


def sentence(state: QueryStateDict, result: Result) -> None:
"""Called when sentence processing is complete"""
print("sentence")
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 and "qkey" in result:
if "qtype" in result:
print("IF QTYPE AND QKEY")
try:
q.set_qtype(result.qtype)
Expand All @@ -326,13 +314,52 @@ 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",
],
"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)
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,
Expand Down
17 changes: 12 additions & 5 deletions queries/sonos.py
Original file line number Diff line number Diff line change
Expand Up @@ -378,12 +378,17 @@ 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()
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}",
Expand All @@ -400,6 +405,8 @@ def play_radio_stream(self, radio_url: str):
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):
Expand Down Expand Up @@ -524,7 +531,7 @@ def play_chime(self):

response = post_to_json_api(url, payload, headers)

print(response)
return response

def next_song(self):
url = f"https://api.ws.sonos.com/control/api/v1/groups/{self._group_id}/playback/skipToNextTrack"
Expand All @@ -536,7 +543,7 @@ def next_song(self):

response = post_to_json_api(url, headers=headers)

print(response)
return response

def prev_song(self):
url = f"https://api.ws.sonos.com/control/api/v1/groups/{self._group_id}/playback/skipToPreviousTrack"
Expand All @@ -548,7 +555,7 @@ def prev_song(self):

response = post_to_json_api(url, headers=headers)

print(response)
return response

# def _refresh_data(self, function):
# print("refresh data")
Expand Down
Loading

0 comments on commit e655d8d

Please sign in to comment.