def speak(person_name, location_name, ignore_motion, ignore_confirmation, voice_id, no_audio, simulate, fail_confirm): try: while True: click.echo("Checking for messages . . .") lm = LocationManager() loc = lm.get_location(location_name) if not ignore_motion and not loc.is_motion: print 'Exiting. No motion detected at ' + location_name exit(1) speaker = Speaker(NoAudio=no_audio) message_manager = MessageManager(LocationName=location_name) click.echo('getting files') cache_manager = CacheManager(BucketName='pollexy-media', CacheName='chimes') cache_manager.sync_remote_folder() print 'Writing speech' vid, speech = message_manager.write_speech(PersonName=person_name) if vid: voice_id = vid if not speech: print "I have nothing to say" message_manager.delete_sqs_msgs() else: print "Speech:\n\n%s" % speech try: pm = PersonManager() p = pm.get_person(person_name) do_speech = True if fail_confirm: logging.warning("FORCE FAILING confirmation") reason, do_speech = "NoResponse", False elif not no_audio and p.require_physical_confirmation and \ not ignore_confirmation: lv = LocationVerification(PersonName=person_name, LocationName=location_name, VoiceId=voice_id) do_speech, retry_count, timeout = \ lv.verify_person_at_location(SpeechMethod=say) if do_speech: speaker = Speaker(NoAudio=no_audio) speaker.generate_audio(Message=speech, TextType='ssml', VoiceId=voice_id) speaker.speak(IncludeChime=True) message_manager.succeed_speech(dont_delete=simulate) else: message_manager.fail_speech(Reason=reason) finally: speaker.cleanup() except Exception as exc: exc_type, exc_value, exc_traceback = sys.exc_info() print repr( traceback.format_exception(exc_type, exc_value, exc_traceback)) click.echo("Error: %s" % str(exc)) exit(2)
def queue(simulate, simulated_date): try: if simulated_date: dt = arrow.get(simulated_date) else: dt = arrow.utcnow() scheduler = Scheduler() print 'getting messages' msgs = scheduler.get_messages() logging.info("Starting MessageManager") logging.info("messages = %s" % len(msgs)) if len(msgs) == 0: click.echo("No messages are ready to be queued") else: click.echo("Number of messages to be scheduled: %s" % len(msgs)) for m in msgs: if not simulate: logging.info("Getting person %s " % m.person_name) pm = PersonManager() p = pm.get_person(m.person_name) if not p: logging.warn(m.person_name + "does not have an entry in the " + "Person table") continue if p.all_available_count(dt) == 0: logging.warn('No locations available for %s' % m.person_name) click.echo('No locations available for %s' % m.person_name) continue avail_windows = p.all_available(dt) click.echo('# of locations avail: {}, last_loc={}'.format( p.all_available_count(dt), m.last_loc)) if m.last_loc == p.all_available_count(dt) - 1: click.echo('Resetting to first location') idx = 0 else: click.echo('Moving to next location') idx = m.last_loc + 1 active_window = avail_windows[int(idx)] next_exp = m.next_expiration_utc.isoformat() mm = MessageManager(LocationName=active_window.location_name) click.echo("Publishing message for person %s to location %s" % (m.person_name, active_window.location_name)) mm.publish_message(Body=m.body, UUID=m.uuid_key, PersonName=m.person_name, NoMoreOccurrences=m.no_more_occurrences, ExpirationDateTimeInUtc=next_exp) scheduler.update_queue_status(m.uuid_key, m.person_name, True) scheduler.update_last_location(m.uuid_key, m.person_name, idx) else: click.echo("Publishing message(simulated):") click.echo(str(m)) except Exception: print 'here' click.echo(traceback.print_exc()) raise
def test_person_location_out_of_order_priorities_are_correct(): p = Person(Name='calvin') now_dt = arrow.get('2014-01-01T09:09:00.000-05:00') tw = PersonTimeWindow(LocationName='kitchen', Priority=100, ical=ical_event, CompareDateTime=now_dt) p.add_window(tw) tw = PersonTimeWindow(LocationName='media_room', Priority=300, ical=ical_event, CompareDateTime=now_dt) p.add_window(tw) tw = PersonTimeWindow(LocationName='bedroom', Priority=200, ical=ical_event, CompareDateTime=now_dt) p.add_window(tw) pm = PersonManager() pm.update_window_set(p) with patch.object(Scheduler, 'get_messages', return_value=[mock_message1]): runner = CliRunner() result = runner.invoke(cli, obj=Config(), args=[ '--location_name', 'test', '--simulate_dt', now_dt.isoformat(), 'queue' ]) if result.exit_code > 0: exc_type, exc_value, exc_traceback = result.exc_info logging.error( traceback.format_exception(exc_type, exc_value, exc_traceback)) assert 'Publishing message for person calvin to location media_room' in \ result.output
def test_person_req_phys_conf_sets_req_phys_conf_for_loc_verify(p_mock): pm = PersonManager() p = Person(Name='calvin') p.require_physical_confirmation = True pm.update_window_set(p) lv = LocationVerification(LocationName='room', PersonName='calvin') assert lv.person.require_physical_confirmation
def delete_person(person_name): pm = PersonManager() p = pm.get_person(person_name) if p is None: click.echo('{} does not exist'.format(person_name)) else: pm.delete(PersonName=person_name) click.echo('{} deleted'.format(person_name))
def person_show(name): pm = PersonManager() p = pm.get_person(name) if person is None: click.echo("{} does not exist in the system".format(name)) else: click.echo('{} (req_phys={})'.format(p.name, p.require_physical_confirmation))
def queue_message(intent, session): card_title = intent['name'] session_attributes = {} should_end_session = False reprompt_text = 'Excuse me?' if 'person' in intent['slots'] and 'message' in intent['slots']: if 'voice' in intent['slots']: voice = str(intent['slots']['voice']['value']) else: voice = 'Joanna' person = str(intent['slots']['person']['value']).lower() name = intent['slots']['message']['value'] dt = arrow.utcnow() pm = PersonManager() p = pm.get_person(person) lm = LibraryManager() m = lm.get_message(Name=name) if not p: logging.error('{} does not have an entry in the ' 'Person table . . .'.format(person)) speech_output = "Sorry, I don't know the name {}" \ .format(person) should_end_session = True elif not m: logging.error('There is no message named {}'.format(name)) speech_output = "Sorry, I don't have a message named {}" \ .format(name) should_end_session = True elif p.all_available_count(dt) == 0: logging.error('No locations are available for {}'.format(person)) speech_output = "Sorry, there are no locations for {}" \ .format(name) should_end_session = True else: active_window = p.all_available(dt)[0] mm = MessageManager(LocationName=active_window.location_name) speech_output = "Got it. Publishing message {} to {} at " \ "location {}".format(name, person, active_window.location_name) mm.publish_message(Body=m['message'], PersonName=person, Voice=voice) should_end_session = True else: logging.error('Missing person or message') speech_output = 'Person or message name is missing. Please try again' should_end_session = True return build_response( session_attributes, build_speechlet_response(card_title, speech_output, reprompt_text, should_end_session))
def person_list(): pm = PersonManager() people = pm.get_all() if people is None: click.echo("There are no people in the system") else: for p in people: click.echo('{} (req_phys={})'.format( p.name, p.require_physical_confirmation))
def person_availability(person_name): pm = PersonManager() p = pm.get_person(person_name) locs = p.all_available() if len(locs) > 0: for l in locs: print l.location_name else: print "No locations are currently acrive"
def test_no_locations_returns_error(c_mock, l_mock): e = test_event() lm = LibraryManager() lm.update_message(Name='dinner', Message='time for dinner') pm = PersonManager() p = Person(Name='calvin') pm.update_window_set(p) c_mock.return_value = 0 handler(e, {}) l_mock.assert_called_with('No locations are available for calvin')
def person_list(): pm = PersonManager() people = pm.get_all() if people is None: click.echo("There are no people in the system") else: for p in people: click.echo('{} (req_phys={})'.format( p.name, p.require_physical_confirmation)) for tw in json.loads(p.time_windows.to_json()): print '--{}\n{}'.format(tw['location_name'], tw['ical'])
def test_add_with_false_phys_conf_sets_false(): event = { 'message': { 'Name': calvin_name, 'RequirePhysicalConfirmation': False } } handler(event, ctx) pm = PersonManager() p = pm.get_person(calvin_name) assert not p.require_physical_confirmation
def handler(event, context): scheduler = Scheduler() dt = arrow.utcnow() logging.info("Getting messages") msgs = scheduler.get_messages() logging.info("messages = %s" % len(msgs)) if len(msgs) == 0: logging.info("No messages are ready to be queued") else: logging.info("Number of messages to be scheduled: %s" % len(msgs)) for m in msgs: logging.info("Getting person %s " % m.person_name) pm = PersonManager() p = pm.get_person(m.person_name) if not p: logging.warn(m.person_name + "does not have an entry in the " + "Person table . . . skipping") continue if p.all_available_count(dt) == 0: logging.warn('No locations available for %s . . . skipping' % m.person_name) continue avail_windows = p.all_available(dt) logging.info('# of locations avail: {}, last_loc={}'.format( p.all_available_count(dt), m.last_loc)) if p.all_available_count(dt) > 1 and \ m.last_loc == p.all_available_count(dt)-1: logging.info('Resetting to first location') idx = 0 else: if p.all_available_count(dt) > 1: logging.info('Moving to next location') idx = m.last_loc + 1 else: idx = 0 active_window = avail_windows[int(idx)] next_exp = m.next_expiration_utc.isoformat() mm = MessageManager(LocationName=active_window.location_name) logging.info("Publishing message for person %s to location %s" % (m.person_name, active_window.location_name)) mm.publish_message(Body=m.body, UUID=m.uuid_key, PersonName=m.person_name, NoMoreOccurrences=m.no_more_occurrences, BotNames=m.bot_names, IceBreaker=m.ice_breaker, RequiredBots=m.required_bots, ExpirationDateTimeInUtc=next_exp) scheduler.update_queue_status(m.uuid_key, m.person_name, True) scheduler.update_last_location(m.uuid_key, m.person_name, idx)
def publish_message(self, **kwargs): """publish a single message to the queue""" expiration_date = kwargs.pop('ExpirationDateTimeInUtc', '2299-12-31 00:00:00') body = kwargs.pop('Body', '') uuid_key = kwargs.pop('UUID', str(uuid.uuid4())) no_more_occ = kwargs.pop('NoMoreOccurrences', False) person_name = kwargs.pop('PersonName', '') voice = kwargs.pop('VoiceId', 'Joanna') if not person_name: raise ValueError("No person provided") if not uuid_key: raise ValueError("No uuid provided") if not body: raise ValueError('No message body provided') if kwargs: raise TypeError('Unexpected **kwargs: %r' % kwargs) logging.info("************************") pm = PersonManager() p = pm.get_person(person_name) windows = p.time_windows.to_json() self.queue.send_message(MessageBody=body, MessageAttributes={ 'PersonName': { 'StringValue': person_name, 'DataType': 'String' }, 'Locations': { 'StringValue': windows, 'DataType': 'String' }, 'ExpirationDateTimeInUtc': { 'StringValue': expiration_date, 'DataType': 'String' }, 'UUID': { 'StringValue': uuid_key, 'DataType': 'String' }, 'NoMoreOccurrences': { 'StringValue': str(no_more_occ), 'DataType': 'String' }, 'Voice': { 'StringValue': voice, 'DataType': 'String' } })
def test_unmute_person_unmutes_person(): pm = PersonManager() pm.toggle_mute('calvin', True) p = pm.get_person('calvin') assert p.is_muted pm.toggle_mute('calvin', False) p = pm.get_person('calvin') assert not p.is_muted
def person_update(name, req_phys_confirmation, no_phys_confirmation, location_windows): pm = PersonManager() if req_phys_confirmation: req_phys = True elif no_phys_confirmation: req_phys = False else: req_phys = None pm.update_person(Name=name, RequirePhysicalConfirmation=req_phys, Windows=location_windows)
def test_preference_is_sorted_correctly(): pm = PersonManager() p = Person(Name='calvin') now_dt = arrow.get('2014-01-01T07:10:00.000-05:00') tw = PersonTimeWindow(LocationName='kitchen', Priority=100, ical=ical_event_before_school, CompareDateTime=now_dt) p.add_window(tw) tw = PersonTimeWindow(LocationName='bedroom', Priority=200, ical=ical_event_before_school, CompareDateTime=now_dt) p.add_window(tw) pm.update_window_set(p) assert p.all_available(now_dt)[0].priority == 200 assert p.all_available(now_dt)[1].priority == 100 tw = PersonTimeWindow(LocationName='mediaroom', Priority=50, ical=ical_event_before_school, CompareDateTime=now_dt) p.add_window(tw) pm.update_window_set(p) p = pm.get_person('calvin') assert p.all_available(now_dt)[0].priority == 200 assert p.all_available(now_dt)[1].priority == 100 assert p.all_available(now_dt)[2].priority == 50
def test_verify_switch_with_press_returns_true(): rpi_mock.GPIO.setmode.return_value = None rpi_mock.GPIO.setup.return_value = None rpi_mock.GPIO.input.return_value = False pm = PersonManager() p = Person(Name='calvin') p.require_physical_confirmation = True pm.update_window_set(p) l = LocationAvailability(LocationName='kitchen') id = 12 l.with_switch(HardwareId=id, Color='Red', Name='Test', Style='Circle') lm = LocationManager() lm.update_input_capabilities(l) lv = LocationVerification(LocationName='kitchen', PersonName='calvin') done, count, timeout = lv.verify_person_at_location() print done, count, timeout assert done and count == 1 and timeout < 3
def test_saving_person_with_available_windows_are_available(): now_dt = arrow.get('2014-01-01T09:09:00.000-05:00') pm = PersonManager() p = Person(Name='calvin') now_dt = arrow.get('2014-01-01T09:09:00.000-05:00') tw = PersonTimeWindow(LocationName='kitchen', Priority=100, ical=ical_event, CompareDateTime=now_dt) p.add_window(tw) tw = PersonTimeWindow(LocationName='bedroom', Priority=200, ical=ical_event, CompareDateTime=now_dt) p.add_window(tw) pm.update_window_set(p) assert p.all_available_count(now_dt) == 2
def test_saving_person_window_set_saves_set(): pm = PersonManager() p = Person(Name='calvin') now_dt = arrow.get('2014-01-01T09:09:00.000-05:00') tw = PersonTimeWindow(LocationName='kitchen', Priority=100, ical=ical_event, CompareDateTime=now_dt) p.add_window(tw) tw = PersonTimeWindow(LocationName='bedroom', Priority=200, ical=ical_event, CompareDateTime=now_dt) p.add_window(tw) pm.update_window_set(p) p = pm.get_person('calvin') assert p.time_windows.count() == 2
def calvin_three_rooms(now_dt): p = Person(Name='calvin') tw = PersonTimeWindow(LocationName='kitchen', Priority=100, ical=ical_event, CompareDateTime=now_dt) p.add_window(tw) tw = PersonTimeWindow(LocationName='media_room', Priority=300, ical=ical_event, CompareDateTime=now_dt) p.add_window(tw) tw = PersonTimeWindow(LocationName='bedroom', Priority=200, ical=ical_event, CompareDateTime=now_dt) p.add_window(tw) pm = PersonManager() pm.update_window_set(p)
def person_update(name, req_phys_confirmation, no_phys_confirmation, location_windows): pm = PersonManager() if req_phys_confirmation: req_phys = True elif no_phys_confirmation: req_phys = False else: req_phys = None try: pm.update_person(Name=name, RequirePhysicalConfirmation=req_phys, Windows=location_windows) except Exception as e: print "Error creating user: {}".format(e) click.echo("Upserted user {}".format(name))
def __init__(self, **kwargs): self.location_name = kwargs.get('LocationName', '') self.person_name = kwargs.get('PersonName', '') self.voice = kwargs.get('VoiceId', 'Joanna') self.lex = LexSession(bot="PlexyMessenger", alias="$LATEST", user=self.location_name) self.person = PersonManager().get_person(self.person_name) self.location = LocationManager().get_location(self.location_name) self.timeout_in_secs = kwargs.get('TimeoutInSeconds', 15) self.retry_count = kwargs.get('RetryCount', 4)
def test_updating_name_only_add_name_only(): event = {'message': {'Name': calvin_name}} handler(event, ctx) pm = PersonManager() p = pm.get_person(calvin_name) assert p.name == calvin_name
def test_with_window_set_saves(): event = {'message': {'Name': calvin_name, 'WindowSet': window_set}} handler(event, ctx) pm = PersonManager() p = pm.get_person(calvin_name) assert p.time_windows.count() == 2
def publish_message(self, **kwargs): expiration_date = kwargs.pop('ExpirationDateTimeInUtc', '2299-12-31 00:00:00') body = kwargs.pop('Body', '') uuid_key = kwargs.pop('UUID', str(uuid.uuid4())) no_more_occ = kwargs.pop('NoMoreOccurrences', False) person_name = kwargs.pop('PersonName', '') bot_names = kwargs.pop('BotNames', None) required_bots = kwargs.pop('RequiredBots', None) ice_breaker = kwargs.pop('IceBreaker', None) voice = kwargs.pop('VoiceId', 'Joanna') if not person_name: raise ValueError("No person provided") if not uuid_key: raise ValueError("No uuid provided") if not body: raise ValueError('No message body provided') if kwargs: raise TypeError('Unexpected **kwargs: %r' % kwargs) pm = PersonManager() p = pm.get_person(person_name) windows = p.time_windows.to_json() msg_attr = { 'PersonName': { 'StringValue': person_name, 'DataType': 'String' }, 'Locations': { 'StringValue': windows, 'DataType': 'String' }, 'ExpirationDateTimeInUtc': { 'StringValue': expiration_date, 'DataType': 'String' }, 'UUID': { 'StringValue': uuid_key, 'DataType': 'String' }, 'NoMoreOccurrences': { 'StringValue': str(no_more_occ), 'DataType': 'String' }, 'Voice': { 'StringValue': voice, 'DataType': 'String' } } if required_bots: msg_attr['RequiredBots'] = { 'StringValue': required_bots, 'DataType': 'String' } if bot_names: msg_attr['BotNames'] = { 'StringValue': bot_names, 'DataType': 'String' } if ice_breaker: msg_attr['IceBreaker'] = { 'StringValue': ice_breaker, 'DataType': 'String' } if bot_names: self.log.debug('Publishing to bot queue') self.bot_queue.send_message(MessageBody=body, MessageAttributes=msg_attr) else: self.log.debug('Publishing to message queue') self.queue.send_message(MessageBody=body, MessageAttributes=msg_attr) self.log.debug(body)
def speak(person_name, location_name, ignore_motion, ignore_confirmation, voice_id, no_audio, simulate, fail_confirm, verbose): log = logging.getLogger('PollexyCli') if verbose: os.environ['LOG_LEVEL'] = 'DEBUG' log.setLevel(logging.DEBUG) try: while True: lm = LocationManager() loc = lm.get_location(location_name) if not ignore_motion and not loc.is_motion: print 'Exiting. No motion detected at ' + location_name exit(1) speaker = Speaker(NoAudio=no_audio) message_manager = MessageManager(LocationName=location_name) bm = message_manager.get_messages(MessageType='Bot', PersonName=person_name) if bm and len(bm) > 0: log.debug('Bot count = {}'.format(len(bm))) for bot in bm: username = str(uuid.uuid4()) try: lp = LexPlayer( BotNames=bot.bot_names, Alias="$LATEST", Username=username, VoiceId=voice_id, IceBreaker=bot.ice_breaker, Introduction=bot.introduction, NoAudio=no_audio, BotsRequired=bot.required_bots) while (not lp.is_done): lp.get_user_input() except Exception as e: print 'Bot failed: {}'.format(e) raise message_manager.succeed_messages(dont_delete=simulate) cache_manager = CacheManager(BucketName='pollexy-media', CacheName='chimes') cache_manager.sync_remote_folder() vid, speech = message_manager.write_speech(PersonName=person_name) if vid: voice_id = vid if not speech: message_manager.succeed_messages(dont_delete=simulate) message_manager.delete_sqs_msgs() else: try: pm = PersonManager() p = pm.get_person(person_name) do_speech = True if fail_confirm: log.warn("FORCE FAILING confirmation") reason, do_speech = "NoResponse", False elif not no_audio and p.require_physical_confirmation and \ not ignore_confirmation: lv = LocationVerification(PersonName=person_name, LocationName=location_name, VoiceId=voice_id) do_speech, retry_count, timeout = \ lv.verify_person_at_location(SpeechMethod=say) log.debug('do_speech={}'.format(bool(do_speech))) if fail_confirm: message_manager.fail_messages(Reason=reason) else: if do_speech: log.debug('starting speech') speaker = Speaker(NoAudio=no_audio) speaker.generate_audio(Message=speech, TextType='ssml', VoiceId=voice_id) speaker.speak(IncludeChime=True) log.debug('Succeeding messages') message_manager.succeed_messages(dont_delete=simulate) finally: speaker.cleanup() except Exception as exc: exc_type, exc_value, exc_traceback = sys.exc_info() print repr(traceback.format_exception(exc_type, exc_value, exc_traceback)) click.echo("Error: %s" % str(exc)) exit(2)
def queue(simulate, simulated_date, verbose): log = logging.getLogger('PollexyCli') if verbose: os.environ['LOG_LEVEL'] = 'DEBUG' log.setLevel(logging.DEBUG) try: if simulated_date: dt = arrow.get(simulated_date) else: dt = arrow.utcnow() scheduler = Scheduler() msgs = scheduler.get_messages() if len(msgs) == 0: click.echo("No messages are ready to be queued") return log.debug("Number of messages to be scheduled: %s" % len(msgs)) for m in msgs: if not simulate: pm = PersonManager() p = pm.get_person(m.person_name) if not p: log.warn(m.person_name + "does not have an entry in the " + "Person table") continue if p.all_available_count(dt) == 0: log.debug('No locations available for %s' % m.person_name) continue avail_windows = p.all_available(dt) log.debug('# of locations avail: {}, last_loc={}' .format(p.all_available_count(dt), m.last_loc)) if m.last_loc == p.all_available_count(dt)-1: log.debug('Resetting to first location') idx = 0 else: log.debug('Moving to next location') idx = m.last_loc + 1 active_window = avail_windows[int(idx)] next_exp = m.next_expiration_utc.isoformat() mm = MessageManager(LocationName=active_window.location_name) log.debug("Publishing message for person %s to location %s" % (m.person_name, active_window.location_name)) mm.publish_message(Body=m.body, UUID=m.uuid_key, PersonName=m.person_name, NoMoreOccurrences=m.no_more_occurrences, BotNames=m.bot_names, RequiredBots=m.required_bots, IceBreaker=m.ice_breaker, Introduction=m.introduction, ExpirationDateTimeInUtc=next_exp) scheduler.update_queue_status(m.uuid_key, m.person_name, True) scheduler.update_last_location(m.uuid_key, m.person_name, idx) else: click.echo("Publishing message(simulated):") click.echo(str(m)) except Exception: print 'here' click.echo(traceback.print_exc()) raise