def telemetryIntent(self, intent: str, session: DialogSession) -> bool: slots = session.slots siteId = session.siteId if 'siteId' in slots: siteId = session.slotValue('Room') if 'TelemetryType' not in slots: self.continueDialog( sessionId=session.sessionId, text=self.randomTalk('noType'), intentFilter=[self._INTENT_ANSWER_TELEMETRY_TYPE], slot='TelemetryType' ) telemetryType = session.slotValue('TelemetryType') data = self.TelemetryManager.getData(siteId=siteId, ttype=telemetryType) if data and 'value' in data: answer = data['value'] + self._telemetryUnits.get(telemetryType, '') self.endDialog(sessionId=session.sessionId, text=self.randomTalk('answerInstant').format(answer)) else: self.endDialog(sessionId=session.sessionId, text=self.randomTalk('noData')) return True
def playGameIntent(self, intent: str, session: DialogSession) -> bool: sessionId = session.sessionId slots = session.slots if not self._minigame or not self._minigame.started: if 'WhichGame' not in slots: self.continueDialog( sessionId=sessionId, intentFilter=[self._INTENT_ANSWER_MINI_GAME], text=self.TalkManager.randomTalk('whichGame')) elif session.slotValue('WhichGame') not in self._SUPPORTED_GAMES: self.continueDialog( sessionId=sessionId, intentFilter=[ self._INTENT_ANSWER_MINI_GAME, self._INTENT_ANSWER_YES_OR_NO ], text=self.TalkManager.randomTalk('unknownGame'), currentDialogState='answeringPlayAnotherGamer') else: game = session.slotValue('WhichGame') self._minigame = self._minigames[game] self._minigame.start(session) elif self._minigame is not None: self._minigame.onMessage(intent, session) return True
def changeVolume(self, session: DialogSession, **_kwargs): if 'VolumeDirection' not in session.slots and 'ExactVolume' not in session.slots: self.continueDialog(sessionId=session.sessionId, text=self.TalkManager.randomTalk( 'notUnderstood', skill='system')) return players = self.filterPlayers(session) if not players: return for player in players: volume = player.volume if 'ExactVolume' in session.slots: volume = self.Commons.clamp( float(session.slotValue('ExactVolume')), 0, 100) else: if session.slotValue('VolumeDirection') == 'louder': volume = self.Commons.clamp(volume + 10, 0, 100) else: volume = self.Commons.clamp(volume - 10, 0, 100) player.ramp_to_volume(int(volume)) self.endDialog(sessionId=session.sessionId, text=self.randomTalk(text='ok'))
def extractRequestedItemFromList(self, session: DialogSession): intent = session.intentName if intent == self._INTENT_SELECT_ITEM: if 'Number' in session.slotsAsObjects: if session.slotValue('Number') > len(self._dbMessageList): self.logWarning(f'That number appears to be invalid') self.getItemFromList(session) return itemChosen = session.slotValue('Number') itemChosen = int( itemChosen ) - 1 # turn float into a int then subtract 1 for indexing the list self._selectedMessages = self._dbMessageList[ itemChosen] # extract the actual requested message if 'ReminderDelete' in session.slotsAsObjects: self.deleteRequestedReminder(session) elif f'{self._eventType}RemainingTime' in session.slotsAsObjects: self.getTimeRemaining(session) elif f'{self._eventType}Stop' in session.slotsAsObjects: self.userAskedToStopReminder(session) else: self.continueDialog(sessionId=session.sessionId, text='respondNoNumber', intentFilter=[self._INTENT_SELECT_ITEM], currentDialogState='askWhatItemFromList') else: self.logWarning(f'The expected Intent was not received')
def telemetryIntent(self, session: DialogSession): locations = self.LocationManager.getLocationsForSession(sess=session, slotName='Location') siteId = session.slotValue('Location', defaultValue=session.siteId) telemetryType = session.slotValue('TelemetryType') if not telemetryType: self.continueDialog( sessionId=session.sessionId, text=self.randomTalk('noType'), intentFilter=[Intent('AnswerTelemetryType')], slot='Alice/TelemetryType' ) return if len(locations) != 1: self.continueDialog( sessionId=session.sessionId, text="What location?!", #self.randomTalk('noType'), intentFilter=[Intent('AnswerTelemetryType')], slot='Alice/TelemetryType' ) return # siteId=locations[0].name, data = self.TelemetryManager.getData(ttype=TelemetryType(telemetryType), location=locations[0]) if data and 'value' in data.keys(): answer = f"{data['value']} {self._telemetryUnits.get(telemetryType, '')}" self.endDialog(sessionId=session.sessionId, text=self.randomTalk(text='answerInstant', replace=[answer])) else: self.endDialog(sessionId=session.sessionId, text=self.randomTalk('noData'))
def onMessage(self, intent: str, session: DialogSession) -> bool: sessionId = session.sessionId slots = session.slots if not self._minigame or not self._minigame.started: if intent == self._INTENT_PLAY_GAME or ( intent == self._INTENT_ANSWER_MINI_GAME and session.previousIntent == self._INTENT_PLAY_GAME): if 'WhichGame' not in slots.keys(): self.continueDialog( sessionId=sessionId, intentFilter=[self._INTENT_ANSWER_MINI_GAME], text=self.TalkManager.randomTalk('whichGame'), previousIntent=self._INTENT_PLAY_GAME) elif session.slotValue( 'WhichGame') not in self._SUPPORTED_GAMES: self.continueDialog( sessionId=sessionId, intentFilter=[ self._INTENT_ANSWER_MINI_GAME, self._INTENT_ANSWER_YES_OR_NO ], text=self.TalkManager.randomTalk('unknownGame'), previousIntent=self._INTENT_PLAY_GAME) else: game = session.slotValue('WhichGame') self._minigame = self._minigames[game] self._minigame.start(session) elif intent == self._INTENT_ANSWER_YES_OR_NO: if not commons.isYes(session): self.endDialog(sessionId=sessionId, text=self.randomTalk('endPlaying')) else: self.continueDialog( sessionId=sessionId, intentFilter=[self._INTENT_ANSWER_MINI_GAME], text=self.TalkManager.randomTalk('whichGame'), previousIntent=self._INTENT_PLAY_GAME) elif self._minigame is not None: if intent == self._INTENT_ANSWER_YES_OR_NO and session.customData and 'askRetry' in session.customData.keys( ): if commons.isYes(session): self._minigame.start(session) else: self._minigame = None self.endDialog(sessionId=sessionId, text=self.randomTalk('endPlaying')) else: self._minigame.onMessage(intent, session) return True
def preSession(self, siteId: str, user: str) -> DialogSession: """ Pre sessions hold the speaker based on the site id. They are deleted as soon as a session id is attributed to the related dialog :param siteId: int :param user: string """ session = DialogSession(siteId) session.user = user self._preSessions[siteId] = session return session
def forgeUserRandomAnswer(self, session: DialogSession): """ Forges a session and sends an onIntentParsed as if an intent was captured :param session: :return: """ session.payload['input'] = session.payload['text'] session.payload.setdefault('intent', dict()) session.payload['intent']['intentName'] = 'UserRandomAnswer' session.payload['intent']['confidenceScore'] = 1.0 session.payload['alternatives'] = list() session.payload['slots'] = list() self.onIntentParsed(session)
def setupTheStation(self, session: DialogSession, **_kwargs): # Read the config.json.template file to get the list of values self._data = self.readTemplateData() # If user has not specified a station, just play the default station if not 'RadioStation' in session.slotsAsObjects and not 'number' in session.slotsAsObjects: self.playExistingStation(session=session) return # If user specified the station, match it up to the url # if user specified a number, select that line from the list if available if session.slotValue('number'): listLength = len(self._data) number: int = session.slotValue('number') # if user asks for list number that doesn't exist if number > listLength: self.logWarning('Number requested was larger than list... aborting') self.endDialog( text='Provided number was out of range. Ask me again correctly' ) return else: counter = 1 for item in self._data: # update the config with selected url via number selection if counter == number: if self._data.get(item) == self.getConfig('radioStations'): return self.playExistingStation(session) self._selectedStation = self._data.get(item) self.updateConfig(key='radioStations', value=self._selectedStation) return self.playExistingStation(session) counter += 1 choosenStation = session.slotValue('RadioStation') for key in self._data: # update the config with choosen station via station name if key in choosenStation: # If station being requested is existing station, just play it if self._data.get(key) == self.getConfig('radioStations'): return self.playExistingStation(session) self._selectedStation = self._data.get(key) self.updateConfig(key='radioStations', value=self._selectedStation) return self.playExistingStation(session) else: self.endDialog( text='Couldn\'t find that station. Please try again' )
def mathIntent(self, session: DialogSession): mathOperation = self._mathOperations.get(session.slotValue('Function')) left = float(session.slotValue('Left') or self._lastNumber) right = float(session.slotValue('Right') or 0) if not mathOperation: self.continueDialog(sessionId=session.sessionId, text=self.randomTalk('notUnderstood')) return self._lastNumber = round(mathOperation(left, right), 3) answer = str(self._lastNumber) if self._lastNumber % 1 else str( int(self._lastNumber)) self.endDialog(sessionId=session.sessionId, text=answer)
def determinePreDefinedTimer(self, session: DialogSession): """ Work out what pre determined timer event it is and set the message and time accordingly :param session: the dialog Session :return: """ # set some vars so we can merge the event with existing timer code self._theDeviceId = session.deviceUid self._eventType = 'Timer' self._activeDataBase = self._TIMERDBNAME self._preDefinedEvent = True # work out what pre determined timer the user is requesting if session.slotValue('PreDefinedTimer') == 'wash hands': session.payload['input'] = self.randomTalk(text='washingHands') self.processTheSpecifiedTime(session, preDefinedTime=20) if session.slotValue('PreDefinedTimer') == 'brush teeth': session.payload['input'] = self.randomTalk(text='brushingTeeth') self.processTheSpecifiedTime(session, preDefinedTime=120) if session.slotValue('PreDefinedTimer') == 'cup of tea': session.payload['input'] = self.randomTalk(text='teaReady', replace=['cup']) self.processTheSpecifiedTime(session, preDefinedTime=180) if session.slotValue('PreDefinedTimer') == 'pot of tea': session.payload['input'] = self.randomTalk(text='teaReady', replace=['pot']) self.processTheSpecifiedTime(session, preDefinedTime=420)
def forgeUserRandomAnswer(self, session: DialogSession): """ Forges a session and sends an onIntentParsed as if an intent was captured :param session: :return: """ if 'text' in session.payload: #todo figure out why text sometimes is not filled although input is session.payload['input'] = session.payload['text'] session.payload.setdefault('intent', dict()) session.payload['intent']['intentName'] = 'UserRandomAnswer' session.payload['intent']['confidenceScore'] = 1.0 session.payload['alternatives'] = list() session.payload['slots'] = list() self.onIntentParsed(session)
def newSession(self, siteId: str, user: str = constants.UNKNOWN_USER, message: MQTTMessage = None) -> DialogSession: session = DialogSession(siteId=siteId, user=user, sessionId=str(uuid.uuid4())) if message: session.update(message) self._sessionsById[session.sessionId] = session self._sessionsBySites[siteId] = session return session
def dimLightsIntent(self, session: DialogSession): if 'Percent' not in session.slots: self.continueDialog( sessionId=session.sessionId, text=self.randomTalk('whatPercentage'), intentFilter=[self._INTENT_ANSWER_PERCENT], currentDialogState='whatPercentage' ) return percentage = self.Commons.clamp(session.slotValue('Percent'), 0, 100) brightness = int(round(254 / 100 * percentage)) locations = self._getLocations(session) for location in locations: if location == constants.EVERYWHERE: self._bridge.group(0).brightness = brightness break try: self._bridge.group(groupName=location).brightness = brightness except NoSuchGroup: self.logWarning(f'Requested group "{location}" does not exist on the Philips Hue bridge') if locations: self.endDialog(session.sessionId, text=self.randomTalk('confirm'))
def chooseLocation(self, session: DialogSession): # if user has specified the location in the initial intent do this if 'Location' in session.slotsAsObjects: location = self.LocationManager.getLocationByName( session.slotValue('Location')) if location: self._selectedSat = self.DeviceManager.getDevicesByLocation( locationId=location.id, abilities=[DeviceAbility.PLAY_SOUND]) return if not self._playbackDevice: self.continueDialog( sessionId=session.sessionId, text=self.randomTalk('chooseAnotherLocation'), intentFilter=['BroadcastRoom'], currentDialogState='askingWhatRoomToPlayOn', slot='Location', probabilityThreshold=0.1) elif 'GetBase' in session.slots: self._selectedSat = self._playbackDevice = self.DeviceManager.getMainDevice( ) else: self.continueDialog(sessionId=session.sessionId, text=self.randomTalk('chooseARoom'), intentFilter=['BroadcastRoom'], currentDialogState='askingWhatRoomToPlayOn', slot='Location', probabilityThreshold=0.1)
def onMessage(self, intent: str, session: DialogSession): if intent == self._INTENT_ANSWER_HEADS_OR_TAIL: coin = random.choice(['heads', 'tails']) SuperManager.getInstance().mqttManager.playSound( soundFile=os.path.join(commons.rootDir(), 'modules', 'Minigames', 'sounds', 'coinflip'), sessionId='coinflip', siteId=session.siteId, absolutePath=True) redQueen = SuperManager.getInstance( ).moduleManager.getModuleInstance('RedQueen') redQueen.changeRedQueenStat('happiness', 5) if session.slotValue('HeadsOrTails') == coin: result = 'flipACoinUserWins' redQueen.changeRedQueenStat('frustration', 1) else: result = 'flipACoinUserLooses' redQueen.changeRedQueenStat('frustration', -5) redQueen.changeRedQueenStat('hapiness', 5) SuperManager.getInstance().mqttManager.continueDialog( sessionId=session.sessionId, text=SuperManager.getInstance().talkManager.randomTalk( talk=result, module='Minigames').format( SuperManager.getInstance().languageManager. getTranslations(module='Minigames', key=coin, toLang=SuperManager.getInstance(). languageManager.activeLanguage)[0]), intentFilter=[self._INTENT_ANSWER_YES_OR_NO], previousIntent=self._INTENT_PLAY_GAME, customData={'askRetry': True})
def getWeather(self, session: DialogSession): if not self.getConfig('apiKey'): self.endDialog( sessionId=session.sessionId, text=self.randomTalk('noApiKey') ) return city = session.slotRawValue('City') or self.getConfig('baseLocation') if 'when' not in session.slots: data = self._queryData(city=city) if not data: self.continueDialog( sessionId=session.sessionId, text=self.randomTalk('notFound', replace=[city]), intentFilter=[Intent('AnswerCity')], slot='CityNames', currentDialogState='answeringCity' ) else: self.endDialog( sessionId=session.sessionId, text=self.randomTalk('currentWeather', replace=[ city, round(float(data['main']['temp']), 1), data['weather'][0]['description'] ] ) ) else: # TODO self.endSession(sessionId=session.sessionId)
def onIntentNotRecognized(self, session: DialogSession): if not session.input: return session.previousInput = session.input self.databaseInsert(tableName='notRecognizedIntents', values={'text': session.input})
def newSession(self, deviceUid: str, user: str = constants.UNKNOWN_USER, message: MQTTMessage = None, increaseTimeout: int = 0) -> DialogSession: session = DialogSession(deviceUid=deviceUid, user=user, sessionId=str(uuid.uuid4()), increaseTimeout=increaseTimeout) if message: session.update(message) self._sessionsById[session.sessionId] = session self._sessionsByDeviceUids[deviceUid] = session return session
def randomWordIntent(self, intent: str, session: DialogSession) -> bool: word = session.slots['RandomWord'] if session.previousIntent == self._INTENT_SEARCH: session.customData['userInput'] = word return self.searchIntent(intent=intent, session=session) return False
def doWakewordTuning(self, session: DialogSession): if 'Number' not in session.slotsAsObjects: self.continueDialog( sessionId=session.sessionId, text=self.TalkManager.randomTalk('notUnderstood', skill='system'), intentFilter=[self._INTENT_ANSWER_NUMBER], currentDialogState='answeringWakewordTuningType', probabilityThreshold=0.1) return username = session.customData['username'] sensitivity = self.WakewordManager.getUserWakewordSensitivity(username) if int(session.slotValue('Number')) == 1: self.WakewordManager.setUserWakewordSensitivity( username=username, sensitivity=sensitivity + 0.05) self.ThreadManager.newEvent('TuningWakewordUp').set() self.endDialog(sessionId=session.sessionId, text=self.randomTalk('explainWakewordTuningUp')) else: self.WakewordManager.setUserWakewordSensitivity( username=username, sensitivity=sensitivity - 0.03) self.ThreadManager.newEvent('TuningWakewordDown').set() self.endDialog(sessionId=session.sessionId, text=self.randomTalk('explainWakewordTuningDown'))
def onMessage(self, intent: str, session: DialogSession): if intent == self._INTENT_ANSWER_HEADS_OR_TAIL: coin = random.choice(['heads', 'tails']) SuperManager.getInstance().mqttManager.playSound( soundFile=os.path.join( SuperManager.getInstance().commons.rootDir(), 'skills', 'Minigames', 'sounds', 'coinflip'), sessionId='coinflip', siteId=session.siteId, absolutePath=True) redQueen = SuperManager.getInstance( ).skillManager.getSkillInstance('RedQueen') redQueen.changeRedQueenStat('happiness', 5) if session.slotValue('HeadsOrTails') == coin: result = 'flipACoinUserWins' redQueen.changeRedQueenStat('frustration', 1) else: result = 'flipACoinUserLooses' redQueen.changeRedQueenStat('frustration', -5) redQueen.changeRedQueenStat('hapiness', 5) self.MqttManager.continueDialog( sessionId=session.sessionId, text=self.TalkManager.randomTalk( talk=result, skill='Minigames').format( text=self.LanguageManager.getTranslations( skill='Minigames', key=coin, toLang=SuperManager.getInstance( ).languageManager.activeLanguage)[0]), intentFilter=[self._INTENT_ANSWER_YES_OR_NO], currentDialogState=self.ANSWERING_PLAY_AGAIN_STATE)
def processTheSpecifiedTime(self, session: DialogSession): if f'{self._eventType}DateAndTime' in session.slotsAsObjects: self._spokenDuration = session.slotValue( f'{self._eventType}DateAndTime').split( ) # returns format [2020-04-08, 10:25:00, +10] del self._spokenDuration[-1] # Removes the timezone off the end self._dateTimeStr = ' '.join( self._spokenDuration) # converts the list to a string self._dateTimeObject = datetime.strptime(self._dateTimeStr, '%Y-%m-%d %H:%M:%S') self._secondsDuration = self._dateTimeObject - datetime.today( ) # find the difference between requested time and now if 'Duration' in session.slotsAsObjects: self._secondsDuration = self.Commons.getDuration( session) # Gets the requested duration in seconds self._reminderMessage = session.payload[ 'input'] # set the reminder message if f'{self._eventType}DateAndTime' in session.slotsAsObjects: # Convert to Seconds if its called with DateAndTime slot secs = round(self._secondsDuration.total_seconds()) else: secs = self._secondsDuration # Seconds are already converted so set the secs var if 'Food' in session.slots: self.setFoodTimer(session, secs) else: self.processAndStoreReminder(session, secs)
def onEndSession(self, session: DialogSession, reason: str = 'nominal'): self.enableCaptureFeedback() text = session.payload.get('text', '') if text: session.isEnding = True self.cancelSessionTimeout(sessionId=session.sessionId) self.MqttManager.publish( topic=constants.TOPIC_TTS_SAY, payload={ 'text': session.payload['text'], 'lang': self.LanguageManager.activeLanguageAndCountryCode, 'siteId': session.deviceUid, 'sessionId': session.sessionId }) else: self.MqttManager.publish(topic=constants.TOPIC_SESSION_ENDED, payload={ 'siteId': session.deviceUid, 'sessionId': session.sessionId, 'customData': json.dumps(session.customData), 'termination': { 'reason': reason } })
def onMessage(self, session: DialogSession): if session.intentName == self._INTENT_ANSWER_HEADS_OR_TAIL: coin = random.choice(['heads', 'tails']) self.sound('coinflip', session.siteId) redQueen = SuperManager.getInstance( ).skillManager.getSkillInstance('RedQueen') redQueen.changeRedQueenStat('happiness', 5) if session.slotValue('HeadsOrTails') == coin: result = 'flipACoinUserWins' redQueen.changeRedQueenStat('frustration', 1) else: result = 'flipACoinUserLooses' redQueen.changeRedQueenStat('frustration', -5) redQueen.changeRedQueenStat('happiness', 5) self.MqttManager.continueDialog( sessionId=session.sessionId, text=self.TalkManager.randomTalk( talk=result, skill='Minigames').format( self.LanguageManager.getTranslations(skill='Minigames', key=coin)[0]), intentFilter=[self._INTENT_ANSWER_YES_OR_NO], currentDialogState=self.ANSWERING_PLAY_AGAIN_STATE)
def confirmUsername(self, session: DialogSession): intent = session.intentName if intent == self._INTENT_ANSWER_NAME: username = str(session.slots['Name']).lower() else: username = ''.join([ slot.value['value'] for slot in session.slotsAsObjects['Letters'] ]) if session.slotRawValue('Name') == constants.UNKNOWN_WORD: self.continueDialog( sessionId=session.sessionId, text=self.TalkManager.randomTalk('notUnderstood', skill='system'), intentFilter=[ self._INTENT_ANSWER_NAME, self._INTENT_SPELL_WORD ], currentDialogState='addingUser') return self.continueDialog(sessionId=session.sessionId, text=self.randomTalk(text='confirmUsername', replace=[username]), intentFilter=[self._INTENT_ANSWER_YES_OR_NO], currentDialogState='confirmingUsername', customData={'username': username})
def readyToConvert(self, session: DialogSession, converter, temperatureType: str): spokenTemperature: int = session.slotValue('Number') self.endDialog( session.sessionId, self.randomTalk( text='respondTemperature', replace=[converter(spokenTemperature), temperatureType]))
def onSessionStarted(self, session: DialogSession): """ Session has started, enable Asr and tell it to listen :param session: :return: """ self.startSessionTimeout(sessionId=session.sessionId) session.hasStarted = True
def convertingToCelciusIntent(self, session: DialogSession): if 'Number' not in session.slotsAsObjects: self.askToRepeatWithNumber(session, intentFilta='convert2Celsius') else: self.readyToConvert(session, temperatureType='Celsius', converter=self.convertToCelsius) # Return value for unit testing return session.slotValue('Number')
def publishText(self, session: DialogSession) -> Response: message = MQTTMessage() message.payload = json.dumps({ 'sessionId': session.sessionId, 'siteId': session.deviceUid, 'text': session.input }) session.extend(message=message) self.MqttManager.publish(topic=constants.TOPIC_TEXT_CAPTURED, payload={ 'sessionId': session.sessionId, 'text': session.input, 'device': session.deviceUid, 'likelihood': 1, 'seconds': 1 }) return jsonify(success=True, sessionId=session.sessionId)