def main(arglist): logging.basicConfig( format='%(funcName)s:%(lineno)d %(levelname)s %(message)s', level=logging.INFO) parser = argparse.ArgumentParser() parser.add_argument('--mode', dest='mode', default=RUN_MODE.UPLOAD, help='The mdoe to run Good drive uploader', choices=RUN_MODE.CHOICES) parser.add_argument('--upload', dest='upload', default='', help='Upload a file or directory') args = parser.parse_args(arglist[1:]) if args.mode == RUN_MODE.UPLOAD: if not args.upload: raise ValueError('params --upload required') GoogleDriveUpload.upload_in_shared(args.upload) elif args.mode == RUN_MODE.LISTENER: PORT = 4242 IP = '127.0.0.1' uploader = GoogleDriveUpload() listener = Listener(IP, PORT, uploader) listener.listen()
def main(): """ main function Creates the main Listener and calls listen() Catches the last exception and exit upon that :return: Program returned value """ l = Listener() try: l.listen() except Exception as e: print "Server main() exception: {}".format(e) sys.exit()
def listen(self): print("Starting listen") while self.RUN: listener = Listener() listener.listen() if listener.last_key == "home": if self.TOGGLE: print("Toggling OFF") self.TOGGLE = False else: print("Toggling ON") self.TOGGLE = True if listener.last_key == "end": print("Quitting") self.RUN = False
class Channel: def __init__(self): self.s = None self.l = Listener(self) global c c = self def connect(self): self.s = socket.socket() self.s.connect((cfg.HOST, cfg.PORT)) self.s.send("PASS {}\r\n".format(cfg.PASS).encode()) self.s.send("NICK {}\r\n".format(cfg.NAME).encode()) self.s.send("JOIN #{}\r\n".format(cfg.CHAN).encode()) connected = False while not connected: response = self.s.recv(1024).decode("utf-8") print(response) if "End of /NAMES list" in response: connected = True print("Connected to #" + cfg.CHAN) def chat(self, msg): global last_chat if self.can_chat(): self.s.send("PRIVMSG #{} :{}\r\n".format(cfg.CHAN, msg).encode()) last_chat = time.time() elif cfg.QUEUE: print("message added to queue") queue.append(msg) else: print("message discarded") def listen(self): self.l.listen() def do_queue(self): if cfg.QUEUE and len(queue) > 0: if self.can_chat(): msg = queue.popleft() self.chat(msg) print("message sent from queue") def can_chat(self): return (time.time() - last_chat) > cfg.DELAY
class Hal: """ Hal is our speech assistant and he starts to record spoken words after someone said "Hello Hal". And the speech assistant "Hal" reacts with an answer. """ def __init__(self): self.listener = Listener() self.spoken_words = "" self.interpreter = Interpreter() def activate(self): print("mock: Hal is now activated and listening") print("Hello Dave what can I do for you?") self.main_menu() def main_menu(self): while True: utilities.clear_screen() print("*" * 80) print("Hal main menu") print("*" * 80) print("\t press 1 to talk to Hal") print("\t press 2 to turn off Hal") inp = input("Please type 1 or 2 and press enter:") if inp == "1": self.start_listening() elif inp == "2": sys.exit() else: input( "Wrong command please press enter to continue and repeat") def start_listening(self): self.spoken_words = self.listener.listen() self.interpreter.execute(self.spoken_words) self.spoken_words = self.listener.listen() @staticmethod def error(message=''): print(message) input('Invalid input. Please press enter to continue. ')
class Server(object): def __init__(self, host: str = "0.0.0.0", port: int = 9494): self._processor = Processor() self._response_queue = ResponseQueue() self._listener = Listener(host, port) self._init() def _init(self): self._listener.add_subscriber(self._processor.enqueue) self._listener.add_subscriber(log_request) self._processor.add_subscriber(self._response_queue.enqueue) def start(self): self._processor.start() self._response_queue.start() self._listener.listen() def web(self, action: Callable): action_name = action.__name__ self._processor.add_action(action_name, action)
class Bot: """ A class that represents the bot conducting the dialogue (SDS) Attributes ---------- _name: str the name of the bot _speaker: Speaker speaker object used for text to speech _listener: Listener listener object used for speech to perform Automatic Speech Recognition _prompt: str colored name of the bot to appear in the terminal _verbose: bool whether the bot should print info about the command it receives (dependency tree, lemmas info) _silent: bool whether the bot should only print replies (no text to speech) _frame_stack: list stack where the bot holds the frames it still has not finished to process _current_frame: Frame current frame the bot is processing _is_over: bool whether the interaction is over """ def __init__(self, name, color, verbose=True, silent=False, menu_path=None): """ Constructor :param name: the bot's name it will use in the dialogues :param color: the color the bot will use in the prompt :param verbose: whether the bot should print info about the command it receives (dependency tree, lemmas info) :param silent: if true, then only use print (no text to speech) :param menu_path: the path of the stored menu """ self._name = name self._speaker = Speaker(rate=150, volume=1) self._listener = Listener(mic_index=0) self._prompt = colored(f'{self._name}: ', color) self._verbose = verbose self._silent = silent self._frame_stack = [] self._current_frame = None self._is_over = False if menu_path is not None: self._load_menu(menu_path) else: self._menu = {"entries": []} # when finished setup, welcome user self._say(self._welcome()) def _say(self, sentence): """ Says the given sentence through the bot speaker object :param sentence: sentence :return: None """ print(f"{self._prompt} {sentence}") if not self._silent: self._speaker.speak(sentence) def listen(self): """ Tries to listen for commands. Loops until the sentence in understood properly or there is a connection error :return: transcribed sentence from voice """ if self._verbose: print(f'{self._prompt} * listening *') res = self._listen() while not res["success"]: err = res["error"] if isinstance(err, sr.UnknownValueError): self._say( "Sorry, I did not hear that, can you say that again?") elif isinstance(err, sr.RequestError): self._say("No connection with the server available") return None res = self._listen() return res["sentence"] def _listen(self): """ A simple proxy to access bot own listener object and obtain the transcription of the voice command issued by the user :return: a response object (see Listener docs) """ response = self._listener.listen() return response def process(self, command): """ Processes the given command :param command: command :return: a proper reply (None if interaction is over) """ # obtain spacy syntax dependency tree parsed = syntax_analysis(command) # if prompted to load last stored menu, or saved current one, do so if contains_text(parsed, "save"): self._save_menu() self._say("Menu saved") return if contains_text(parsed, "load"): self._load_menu() self._say("Menu loaded") return # print info if required if self._verbose: root = parsed.root.text.lower().strip() self._say(f"The root of the sentence is \'{root}\'") print(f"\n{'=' * 5} DEPENDENCIES OF SENTENCE {'=' * 5}") print_dependencies(parsed) print(f"\n{'=' * 5} TOKENS OF SENTENCE {'=' * 5}") print_tokens_info(parsed) # determine frame based on parsed command frame = self._determine_frame(parsed) # change current frame if necessary, storing old one if self._current_frame is None: self._current_frame = frame elif frame is not None and type(frame) != type(self._current_frame): self._frame_stack.insert(0, self._current_frame) # self._say("Ok we will come back to that later") self._current_frame = frame # obtain reply by handling parsed command based on the current frame if isinstance(self._current_frame, EndFrame): self._say(self._goodbye()) self._current_frame = None self._frame_stack = [] return elif isinstance(self._current_frame, AddInfoFrame): reply = self._handle_add_info_frame(parsed) elif isinstance(self._current_frame, AskInfoFrame): reply = self._handle_ask_info_frame(parsed) elif isinstance(self._current_frame, OrderFrame): reply = self._handle_order_frame(parsed) else: # if current frame is still None, could not determine user intention reply = "Sorry, I did not understand that, can you say that again?" self._say(reply) # if frame is not over yet, save current reply for later use if self._current_frame is not None: # self._current_frame.set_last_sentence(reply) self._set_last_sentence() # if older frame stored, restore it # and announce that bot is going back to older frame if self._current_frame is None and len(self._frame_stack) > 0: self._current_frame = self._frame_stack.pop(0) if isinstance(self._current_frame, AddInfoFrame): self._say("Ok now back to your statement") elif isinstance(self._current_frame, AskInfoFrame): self._say("Ok now back to your question") elif isinstance(self._current_frame, OrderFrame): self._say("Ok now back to your order") if self._current_frame.get_last_sentence() is not None: self._say(self._current_frame.get_last_sentence()) def _determine_frame(self, parsed): """ Determines the user intention based upon the parsed command and returns the appropriate frame to handle it :param parsed: parsed command (spacy tree) :return: appropriate frame """ # if command is a question, then user is asking info if is_question(parsed): return AskInfoFrame() # otherwise, count the number of frame triggers for each frame triggers_counts = self._count_frame_triggers(parsed) # could not determine frame if all([v == 0 for v in triggers_counts.values()]): return None # return the frame with the majority of triggers # MIGHT NOT BE THE BEST METHOD frame_name = max(triggers_counts, key=triggers_counts.get) if frame_name == "EndFrame": return EndFrame() elif frame_name == "OrderFrame": return OrderFrame() elif frame_name == "AddInfoFrame": return AddInfoFrame() elif frame_name == "AskInfoFrame": return AskInfoFrame() def _count_frame_triggers(self, parsed): """ Counts the number of keywords for each frame triggered by the given parsed command :param parsed: parsed command :return: a dictionary {frame_name: triggers_count} """ # setup return object res = { "EndFrame": 0, "OrderFrame": 0, "AddInfoFrame": 0, "AskInfoFrame": 0 } # visit tree breadth-first, adding up the triggers along the way nodes = [parsed.root] visited = [] while nodes: node = nodes.pop(0) visited.append(node) if EndFrame.is_trigger(node.lemma_, node.dep_): res["EndFrame"] += 1 if OrderFrame.is_trigger(node.lemma_, node.dep_): res["OrderFrame"] += 1 if AddInfoFrame.is_trigger(node.lemma_, node.dep_): res["AddInfoFrame"] += 1 if AskInfoFrame.is_trigger(node.lemma_, node.dep_): res["AskInfoFrame"] += 1 for child in node.children: if not child in visited: nodes.append(child) return res def _add_menu_entry(self, name, course=None): """ Adds an entry to the bot's menu to choose from :param name: name of the entry (e.g. hamburger) :param course: name of the course (optional, e.g. main course) :return: None """ # consistency checks if self._get_menu_entry(name) is not None: raise EntryAlreadyOnMenu() if course is not None and course not in courses_names: raise CourseNotValid() self._menu["entries"].append({"name": name, "course": course}) def _update_menu_entry(self, name, course=None): """ Updates a menu entry (mainly adding info about course, but can be extended later on if needed) :param name: entry name :param course: course of the entry (e.g. drink) :return: None """ # consistency checks if course is not None and course not in courses_names: raise CourseNotValid() entry = self._get_menu_entry(name) if entry is None: raise EntryNotOnMenu() if entry["course"] is not None: raise EntryAttributeAlreadySet() # update entry for i, entry in enumerate(self._menu["entries"]): if entry["name"] == name: self._menu["entries"][i].update({ "name": name, "course": course }) def _get_menu_entry(self, name): """ Searches the given entry in the bot menu :param name: entry name :return: entry, None if absent """ for i, entry in enumerate(self._menu["entries"]): if entry["name"] == name: return self._menu["entries"][i] return None def _handle_add_info_frame(self, parsed): """ Handles the current AddInfoFrame :param parsed: the parsed command :return: consistent reply """ # consistency check assert isinstance(self._current_frame, AddInfoFrame) # fill current frame slots based on the parsed command reply = "" self._fill_add_info_frame_slots(parsed) # based on the frame slots, handle command if self._current_frame.get_slot("subj") == "menu": # add entry to menu try: entry = self._current_frame.get_slot("obj") self._add_menu_entry(entry) if self._current_frame.get_slot("info") is None: reply = "Ok. What course is it?" self._current_frame.set_waiting_answer(True) else: course = self._current_frame.get_slot("info") self._update_menu_entry(entry, course) reply = "Ok" self._current_frame = None except EntryAlreadyOnMenu: reply = "This entry is already in the menu" self._current_frame = None elif self._current_frame.get_slot("subj") == "course": # add info about course entry = self._current_frame.get_slot("obj") course = self._current_frame.get_slot("info") try: self._update_menu_entry(entry, course) reply = "Ok" self._current_frame = None except EntryAttributeAlreadySet: # TODO: add option to modify entry reply = "{} is already a {}".format( entry, self._get_menu_entry(entry)["course"]) except EntryNotOnMenu: # TODO: add option to add entry reply = "I am sorry, {} is not on the menu".format(entry) except CourseNotValid: reply = "I am sorry, {} is not a course".format(course) return reply def _fill_add_info_frame_slots(self, parsed): """ Fills slots of the current AddInfoFrame based on the information contained in the given parsed command :param parsed: parsed command :return: None """ root_lemma = parsed.root.lemma_ pobj_lemma = obtain_lemma(find_dep(parsed, "pobj")) if root_lemma == "add" or pobj_lemma == "menu": # user wants to add entry to menu # TODO: allow to add entry and specify course at the same time self._current_frame.fill_slot("subj", "menu") entry = obtain_text(find_dep(parsed, "dobj")) self._current_frame.fill_slot("obj", entry) if pobj_lemma in courses_names: # user has also specified course self._current_frame.fill_slot("info", pobj_lemma) elif root_lemma == "is": # user wants to add info about course self._current_frame.fill_slot("subj", "course") entry = obtain_text(find_dep(parsed, "nsubj")) self._current_frame.fill_slot("obj", entry) course = obtain_lemma(find_dep(parsed, "attr")) self._current_frame.fill_slot("info", course) elif self._current_frame.is_waiting_answer(): # user has responded to a previous question from the bot # (up to now, that might be only to add info about course of added entry) root_lemma = obtain_lemma(find_dep(parsed, "ROOT")) attr = obtain_lemma(find_dep(parsed, "attr")) course = root_lemma if root_lemma in courses_names else attr self._current_frame.fill_slot("subj", "course") self._current_frame.fill_slot("info", course) def _handle_ask_info_frame(self, parsed): """ Handles the current AskInfoFrame :param parsed: the parsed command :return: consistent reply """ # consistency check assert isinstance(self._current_frame, AskInfoFrame) # if nothing to ask about... if len(self._menu["entries"]) == 0: reply = "I am sorry, there is nothing on menu today. " \ "Try and add something or load the stored menu first." self._current_frame = None return reply # perform slot filling of current frame self._fill_ask_info_frame_slots(parsed) subj = self._current_frame.get_slot("subj") if subj == "menu": # if asked to see the menu # tell menu (entry, course) for each entry in menu reply = "We have:" for course in courses_names: if len([ entry for entry in self._menu["entries"] if entry["course"] == course ]) == 0: continue for entry in self._menu["entries"]: if entry["course"] == course: reply = f"{reply} {entry['name']}," reply = reply[:-1] reply = f"{reply} for {course};" reply = reply[:-1] else: # if asked about a particular course # tell menu (entry, course) for each entry in menu if course == obj obj = self._current_frame.get_slot("obj") if obj in courses_names: reply = "" for entry in self._menu["entries"]: if entry["course"] == obj: reply = f"{reply} {entry['name']}," if len(reply) == "": reply = f"I'm sorry, we don't have anything for {obj}" else: reply = f"We have{reply[:-1]}" else: # the slot filling went wrong reply = "Sorry, I am not sure I understood your question" self._current_frame = None return reply def _fill_ask_info_frame_slots(self, parsed): """ Fills slots of the current AskInfoFrame based on the information contained in the given parsed command :param parsed: parsed command :return: None """ obj_lemma = obtain_lemma(find_dep(parsed, "dobj")) pobj_lemma = obtain_lemma(find_dep(parsed, "pobj")) if (obj_lemma is not None and obj_lemma == "menu") or \ (pobj_lemma is not None and pobj_lemma == "menu"): # user has asked to know the menu self._current_frame.fill_slot("subj", "menu") else: # user has asked to know a course in particular self._current_frame.fill_slot("subj", "course") # to handle different possible phrasings of the question if obj_lemma is not None and obj_lemma in courses_names: self._current_frame.fill_slot("obj", obj_lemma) elif pobj_lemma is not None and pobj_lemma in courses_names: self._current_frame.fill_slot("obj", pobj_lemma) def _handle_order_frame(self, parsed): """ Handles the current OrderFrame :param parsed: the parsed command :return: consistent reply """ # consistency check assert isinstance(self._current_frame, OrderFrame) # if nothing to order... if len(self._menu["entries"]) == 0: reply = "I am sorry, there is nothing on menu today. " \ "Try and add something or load the stored menu first." self._current_frame = None return reply # try to perform slot filling try: self._fill_order_frame_slots(parsed) except EntryNotOnMenu: reply = "I am sorry, that is not on the menu" return reply # if first interaction and user did not specified anything if len(self._current_frame.filled_slots()) == 0: # if user asked for order recap if self._current_frame.get_asked_recap(): reply = "You did not order anything yet, sir. " \ "I am ready to take your order" else: # user just said something like "i am ready to order" reply = "I am ready to take your order" else: # ongoing interaction if self._current_frame.get_asked_recap(): reply = self._recap_order() self._current_frame.set_asked_recap(False) reply = f"{reply}. Would you like to add something else?" self._current_frame.set_waiting_confirmation(True) elif self._current_frame.is_waiting_confirmation() and \ self._current_frame.get_user_answer() == "yes": # user said he wants something else reply = "Ok, please tell me" self._current_frame.set_waiting_confirmation(False) elif len(self._current_frame.unfilled_slots()) == 0 or \ (self._current_frame.is_waiting_confirmation() and self._current_frame.get_user_answer() == "no"): # user has made a full order or said he does not want anything else reply = "Ok. Your order is complete. It will come right away. Enjoy!" self._current_frame.set_waiting_confirmation(False) self._current_frame = None else: # user has added an entry to the order reply = "Ok. Do you want anything else?" self._current_frame.set_waiting_confirmation(True) return reply def _fill_order_frame_slots(self, parsed): """ Fills slots of the current OrderInfoFrame based on the information contained in the given parsed command :param parsed: parsed command :return: None """ # get needed sentence parts to determine user intention root_lemma = parsed.root.lemma_ xcomp_lemma = obtain_lemma(find_dep(parsed, "xcomp")) dobj_lemma = obtain_lemma(find_dep(parsed, "dobj")) dobj_text = obtain_text(find_dep(parsed, "dobj")) # need text for entry names advmod_lemma = obtain_lemma(find_dep(parsed, "advmod")) intj_lemma = obtain_lemma(find_dep(parsed, "intj")) det_lemma = obtain_lemma(find_dep(parsed, "det")) if self._current_frame.is_waiting_confirmation(): # if bot is waiting for a binary answer ("do you want anything else?") if (root_lemma == "no" or intj_lemma == "no" or det_lemma == "no") \ and \ (root_lemma != "have" and root_lemma != "like" and root_lemma != "take"): # user does not want anything else self._current_frame.set_user_answer("no") return elif (root_lemma == "yes" or intj_lemma == "yes") \ and \ (not OrderFrame.is_trigger(root_lemma, "ROOT")): # user wishes to keep on with his order self._current_frame.set_user_answer("yes") return else: # user did not give a straight answer self._current_frame.set_user_answer(None) elif xcomp_lemma is None and dobj_lemma is None: # user said gibberish (as far as the bot knows...) # best thing is to just say 'that is not on the menu' raise EntryNotOnMenu if dobj_lemma == "order" and advmod_lemma == "so far": # user has asked to recap his order so far self._current_frame.set_asked_recap(True) return if len(self._current_frame.filled_slots()) == 0 and \ xcomp_lemma == "order" and dobj_text is None: # user has just stated he is ready to order, # but has not ordered anything yet return if dobj_text is not None: # user has made an order for a menu entry, # add that to the current order if entry is on menu entry = self._get_menu_entry(dobj_text) if entry is None: raise EntryNotOnMenu() self._current_frame.fill_slot(entry["course"], entry["name"]) def _recap_order(self): """ Recaps the order made by the user so far :return: reply with the recap of the order """ # consistency check assert isinstance(self._current_frame, OrderFrame) reply = "You ordered:" for course in courses_names: order_entry = self._current_frame.get_slot(course) if order_entry is not None: reply = f"{reply} {order_entry} for {course}," reply = f"{reply[:-1]}" return reply def _set_last_sentence(self): if isinstance(self._current_frame, AskInfoFrame): return elif isinstance(self._current_frame, AddInfoFrame): return elif isinstance(self._current_frame, EndFrame): return elif isinstance(self._current_frame, OrderFrame): if len(self._current_frame.filled_slots()) == 0: self._current_frame.set_last_sentence( "I am ready to take your order") else: self._current_frame.set_last_sentence( "Would you like anything else?") self._current_frame.set_waiting_confirmation(True) def _welcome(self): """ Welcom message upon bot startup :return: welcome message """ self._is_over = False return "Hello, how may I help?" def _goodbye(self): """ Goodbye message upon bot termination :return: goodby message """ self._is_over = True return "Here's your bill. Goodbye!" def is_over(self): return self._is_over def _load_menu(self, path=None): """ Loads a menu :param path: menu path :return: None """ if path is None: menus = os.listdir("./menu") menus.sort() path = menus[-1] with open(f"./menu/{path}") as file: self._menu = json.load(file) def _save_menu(self): """ Saves the current menu on disk as a json file, at path timestamp_menu.json :return: None """ with open( f"./menu/{datetime.now().strftime('%Y%m%d-%H%M%S')}_menu.json", 'x') as f: json.dump(self._menu, f)
def main(): """ Accept user voice input and translate it into desired language until user says exit or turn off. """ os.system("flite -voice rms -t 'Booting up computer now'") # See if user has an API key to Google Cloud. If not, just set API_KEY # to None. This tells the program to use Google Web API for speech-to- # text which presumably logs user voice. Google Cloud API requires an # account and credit card but gives the user the option to opt out of # logging. try: with open("./.api_key") as f: API_KEY = validate_api(f.read()) except FileNotFoundError as e: API_KEY = "" # Have LEDs pulse when program is starting up and beep to confirm device is ready listener = Listener(api=API_KEY) listener.breathe() listener.confirmation() # Verbal prompt os.system("flite -voice rms -t 'Device ready'") listener.set_brightness(0.10, True, 0.001) translator = Translator() # Loop for feedback while True: os.system("aplay -q 'beep.wav'") # Prompt user text = listener.listen() # If exit or turn off, break and turn off device. if (translator.translate(text, dest="en").text == "exit" or translator.translate(text, dest="en").text == "turn off" # text == translator.translate("exit", dest="en").text # or text == translator.translate("turn off", dest="en").text ): break # Change language to translate into if translator.translate(text, dest="en").text.startswith("Set target to"): self.set_target(text.split("")[-1]) continue # Change input language (translate 'set source to') if translator.translate(text, dest="en").text.startswith("Set source to"): self.set_source(text.split("")[-1]) continue # Now take the perceived audio and do something with it try: print(f"Google thinks you said:\n{text}") except sr.UnknownValueError: print(f"Google Speech could not understand audio") except sr.RequestError as e: print( f"Could not request results from Google Speech Recognition services: {e}" ) # Speak the translated text if user does not want to exit text = translator.translate(text=text, src=listener.src, dest=listener.target).text # Now sanitize the text text = "".join( [char for char in text if char.isalnum() or char.isspace()]) print(text) os.system(f"flite -voice rms -t {text.__repr__()}") sleep(2) listener.confirmation() print("Continue through the loop") # Pulsate LED once more, hold it, and then turn off device listener.breathe(iterations=1, rest=3) os.system("shutdown 0")
class PahoListener(PahoAwsIot, object): def __init__(self, **kargs): super(PahoListener, self).__init__( topic_sub=kargs['paho']['MQTT_TOPIC_SUB'], ca=kargs['paho']['CA_ROOT_CERT_FILE'], cert=kargs['paho']['THING_CERT_FILE'], key=kargs['paho']['THING_PRIVATE_KEY'], host=kargs['paho']['MQTT_HOST'], port=kargs['paho']['MQTT_PORT'], keepalive=kargs['paho']['MQTT_KEEPALIVE_INTERVAL'], logging=kargs['logging']) self.listener = Listener(pyaudio=kargs['pyaudio'], path_temp=kargs['path_temp'], azure=kargs['azure'], logging=kargs['logging']) self.topic_pub = kargs['paho']['MQTT_TOPIC_PUB'] self.is_debug = kargs['is_debug'] def _on_subscribe(self, mosq, obj, mid, granted_qos): self.logger.info("Subscribed to Topic with QoS: " + str(granted_qos)) # test code if self.is_debug: self.publish( 'raspberrypi/request/listen', request_id=str(uuid.uuid4()), ) def _on_message(self, mosq, obj, msg): """ :param dict msg: dictionary converted from json str topic : raspberrypi/request/{action} int qos : json payload : {"param1": "...", "param2": "..."} action : listen -- payload : null """ try: self.logger.info("Topic: " + str(msg.topic)) self.logger.info("QoS: " + str(msg.qos)) self.logger.info("Payload: " + str(msg.payload)) ack = {} ack['sender'] = 'raspberrypi' # topic 確認 # Level1:既定文字列のチェック levels_pub = msg.topic.split('/', 2) levels_sub = self.topic_sub.split('/') if levels_pub[0] != levels_sub[0]: raise ParamError("invalid topic.") # Level2:typeのチェック if levels_pub[1] != levels_sub[1]: raise ParamError("invalid type.") # Level3:actionのチェックと取得 if len(levels_pub) < 3: raise ParamError("can't find action.") action = levels_pub[2] # action毎の処理 if action == 'listen': ack['action'] = 'listened' # 音声録音とテキスト変換 result = self.listener.listen() ack['result'] = result else: raise ParamError("can't find action.") # 処理終了 self.logger.info('on message success.') except ParamError as e: # 他のメッセージを処理しない self.logger.info(e.description) return except RecognitionError as e: # 通常変換失敗時 self.logger.error(e.description) ack['result'] = "音声の聞き取りに失敗しました。" except Error as e: # その他ユーザエラー全般 self.logger.error(e.description) ack['result'] = "録音処理中にエラーが発生しました。" except Exception as e: # その他エラー全般 self.logger.critical(e) self.logger.critical(util.trace()) ack['result'] = "録音処理中にエラーが発生しました。" # 応答返却 self.publish(self.topic_pub, **ack) self.logger.info('on message complete.') def run(self): self.mqttc.loop_forever() pass
else: print 'Usage : python nxpush.py [--prompt]' sys.exit(0) # getting a session try: connector = NxConnector(url, user, password) connector.openSession() except: logger.error('%s \n >>> ERROR: Invalid username or password ' % url) sys.exit(0) # setting up ocr wrapper try: logger.debug('ocrscript location is %s' % ocrScript) ocr = OcrWrapper(ocrScript) except FileNotFoundError, e: logger.error('Failed to wrap ocr script: ' + str(e)) # listener handler = EventHandler(connector, ocr, mapper) listener = Listener(mapper.keys(), handler) # start listener.listen() logger.debug('nxpush service is running') if __name__ == '__main__': main()
class Macro: def __init__(self): pyautogui.PAUSE = round(uniform(1.5, 2.3), 2) self.listener = Listener() self.search = Search() self.bglistener = None self.waypoints = [] self.end = False def __repr__(self): return f"{len(self.waypoints)} waypoint(s) in macro" def _on_release(self, key): if key == keyboard.Key.esc: self.end = True self.bglistener.stop() print("Ending macro ...") return False def start(self): self.end = False self.bglistener = keyboard.Listener(on_release=self._on_release) self.bglistener.start() print("Macro started ...") while not self.end: for waypoint in self.waypoints: while True: is_success = self.moveTo(waypoint) if is_success: break print("Macro ended ...") def show_waypoints(self): print(f"Current waypoints:") print(f"---------------------------------") for i in range(0, len(self.waypoints)): print(f"{i} : {self.waypoints[i]}") print(f"---------------------------------") def delete_waypoint(self, index): self.waypoints.pop(index) print(f"---------------------------------") for i in range(0, len(self.waypoints)): print(f"{i} : {self.waypoints[i]}") print(f"---------------------------------") def add_waypoint(self): region = self.listener.listen() if not None in region: image = self.search.find_image(region=region) if image: self.waypoints.append({ "position": (region[0], region[1]), "box": (region[2], region[3]), "image": image, }) def moveTo(self, waypoint, random=True): try: pyautogui.PAUSE = round(uniform(1.5, 3.0), 2) print(pyautogui.PAUSE) if not random: pyautogui.moveTo(waypoint["position"], duration=0.2) if self.search.find_image(image=waypoint["image"]): randX = randint( waypoint["position"][0], waypoint["position"][0] + waypoint["box"][0], ) randY = randint( waypoint["position"][1], waypoint["position"][1] + waypoint["box"][1], ) randPosition = (randX, randY) pyautogui.moveTo(randPosition, duration=0.2) return True else: print("\033[91mWaypoint image not found ...\033[0m") return False except: pass
from configurator import Configurator from listener import Listener inputdevice = "/dev/input/event0" configfolder = "./config" Configurator(configfolder, inputdevice).configure() listener = Listener(configfolder, inputdevice) try: listener.listen() except KeyboardInterrupt: listener.stop()
class BotBase: plugins = [] def __init__(self, is_debug): self.__init_base_services(is_debug) self.__init_plugins() self.__init_apps() self.last_msg = time.time() self.__monitoring_thread = threading.Thread(target=self.monitor_apps, daemon=True) self.__monitoring_thread.start() self.__listener = Listener(self) def __init_base_services(self, is_debug): logger = Logger(is_debug, './../logs/') self.log = logger.log self.log('Program is launching') self.keys = KeyManager('./../resources/data.json', logger.log) self.api = ApiManager(self.keys, logger.log) self.sender = Sender('./../resources/', self.keys, self.api, logger.log) self.start_time = datetime.datetime.utcnow() self.BOT_PORT = self.keys.bot_port self.sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) self.sock.bind(('localhost', self.BOT_PORT)) self.__thread_listening_port = threading.Thread( target=self.__listen_port, daemon=True) self.__is_listen_port_sleeping = False self.__is_listen_port_listening = False self.__go_on_sleep = False self.__thread_listening_port.start() self.log('Base services are loaded') def __listen_port(self): self.__is_listen_port_sleeping = False self.log('Listening port %d...' % self.BOT_PORT) sock = self.sock #skip stuff sock.settimeout(0.1) while True: try: sock.recv(8192) except: break while True: sock.settimeout(60 * 60 * 6) try: try: self.__is_listen_port_listening = True msg, addr = sock.recvfrom(1024) time.sleep(0.01) self.__is_listen_port_listening = False msg = msg.decode('utf-8') except socket.timeout: continue self.log(f'Received msg in ports listener from {addr}: {msg}') if msg == 'ping': self.log(f'"pong" sending to {addr[1]}') sock.sendto(b'pong', addr) elif msg == 'update': threading.Thread(target=self.update, daemon=True).start() elif msg == 'exited': for app in self.apps: if app.port == addr[1]: app.is_enabled = False break elif msg == 'stop' and addr[1] == self.BOT_PORT: self.__is_listen_port_sleeping = True while self.__go_on_sleep: time.sleep(0.1) self.__is_listen_port_sleeping = False else: self.log('unknown message') except Exception as e: self.sock.close() self.sender.report( f'Exception in ports listener:\n{str(type(e))}\n{str(e)}') self.log( f'!!ERROR!!\nException in ports listener:\n{str(type(e))}\n{str(e)}' ) break def __init_plugins(self): modules = [ x[:-3] for x in os.listdir('./../plugins') if x.endswith('.py') ] imports = [] for x in modules: try: imports.append(__import__(x)) except Exception as e: self.sender.report( f'Exception in the import module({x}):\n{str(type(e))}\n{str(e)}' ) self.log(f'Imported modules: {str(modules)}') all_classes = [] for x in imports: for cls in inspect.getmembers(x, inspect.isclass): if SuperPlugin in cls[1].__bases__: all_classes.append(cls[1]) classes = [] for x in all_classes: if x not in classes: classes.append(x) self.log(f'Loaded classes: {str(classes)}') for x in classes: self.plugins.append(x(self)) self.log('Plugins are loaded') def update(self): self.__init_apps() self.__listener.apps = self.apps def __init_apps(self): class App: def __init__(self, name, port, cmds, prefixes, folder, is_enabled, launch_time): self.name = name self.port = port self.cmds = cmds self.prefixes = prefixes self.folder = folder self.is_enabled = is_enabled self.is_port_busy = True self.last_act = 0 self.last_check = 0 self.launch_time = launch_time self.check_state = 0 apps = [] path_shit = './../apps/' dirs = os.listdir(path_shit) for dirr in dirs: config_path = path_shit + dirr + '/config' if not os.path.exists(config_path): continue try: with open(config_path, 'r', encoding='utf-8') as file: s1 = file.readline() assert (s1.startswith('port=') ), 'Config file is uncorrect (port)' port = int(s1[5:-1]) s2 = file.readline() assert (s2.startswith('commands=') ), 'Config file is uncorrect (commands)' cmds_str = s2[9:-1] cmds_dict = ast.literal_eval(cmds_str) s3 = file.readline() assert (s3.startswith('prefixes=') ), 'Config file is uncorrect (prefixes)' prefixes_str = s3[9:-1] prefixes_dict = ast.literal_eval(prefixes_str) s4 = file.readline() assert (s4.startswith('name=') ), 'Config file is uncorrect (name)' name = s4[5:-1] s5 = file.readline() assert (s5.startswith('launch_time=') ), 'Config file is uncorrect (launch_time)' launch_time = float(s5[12:-1]) one_app = App(name, port, cmds_dict, prefixes_dict, dirr, False, launch_time) apps.append(one_app) self.log(f'Loaded app "{name}" with port {port}') except Exception as e: self.log( f'!!ERROR!!\nAttempt to load app is unsuccessfully:\n{str(type(e))}\n{str(e)}' ) self.apps = apps for app in apps: self.check_connection(app) def send_to_port(self, msg, app, timeout=1, max_ans_size=1024): app.is_port_busy = True sock = self.sock while not self.__is_listen_port_listening: pass self.__go_on_sleep = True sock.sendto(b'stop', ('localhost', self.BOT_PORT)) while not self.__is_listen_port_sleeping: pass sock.settimeout(timeout) self.log(f'"{msg}" sending to app"{app.name}":{app.port}') sock.sendto(msg.encode('utf-8'), ('localhost', app.port)) try: ans, addr = sock.recvfrom(max_ans_size) self.__go_on_sleep = False app.is_port_busy = False ans = ans.decode('utf-8') if addr[1] != app.port: shit = app.name self.log(f'Answer came from {shit}: {ans}') self.sender.report( 'Произошла коллизия. Ожидался запрос от одного порта, получился другой' ) return None self.log(f'App "{app.name}":{app.port} responded: {ans}') return ans except (ConnectionResetError, socket.timeout) as e: self.__go_on_sleep = False self.log(f'App "{app.name}":{app.port} doesn\'t respond') app.is_enabled = False return None def __update_states(self): for app in self.apps: lnc = time.time() - app.launch_time cha = time.time() - app.last_act if lnc < 5.0 * 60.0 or cha < 1.0 * 60.0: app.check_state = 1 elif lnc < 1.0 * 60.0 * 60.0 or cha < 5.0 * 60.0: app.check_state = 2 elif lnc < 4.0 * 60.0 * 60.0 or cha < 20.0 * 60.0: app.check_state = 3 elif lnc < 24.0 * 60.0 * 60.0 or cha < 60.0 * 60.0: app.check_state = 4 elif lnc > 24.0 * 60.0 * 60.0: app.check_state = 5 def __collect_check_list(self): for i in range(len(self.apps)): app = self.apps[i] if app.is_enabled == False or app.is_port_busy: continue if app.check_state == 1: yield i elif app.check_state == 2 and time.time() - app.last_check > 60.0: yield i elif app.check_state == 3 and time.time( ) - app.last_check > 5.0 * 60.0: yield i elif app.check_state == 4 and time.time( ) - app.last_check > 30.0 * 60.0: yield i elif app.check_state == 5 and time.time( ) - app.last_check > 60.0 * 60.0: yield i def monitor_apps(self): time.sleep(10) try: while True: self.__update_states() check_list = list(self.__collect_check_list()) if len(check_list) == 0: time.sleep(11) continue for i in check_list: app = self.apps[i] if app.is_enabled == True and not app.is_port_busy and time.time( ) - self.last_msg > 3.0: app.last_check = time.time() ans = self.send_to_port('is_all_right', app, 0.6, 8) if ans == None: self.sender.report( f'Приложение {app.name} внезапно перестало отвечать' ) self.log( f'!!ERROR!!\nApp {app.name} suddenly stopped responding' ) app.is_enabled = False elif ans == '1': self.sender.report( f'Процесс приложения {app.name} неожиданно завершил работу' ) self.log( f'!!ERROR!!\nThread of app {app.name} crashed') elif ans != '2' and ans != '0': self.sender.report( 'Неожиданный ответ в функции BotBase.monitor_apps. Посмотри логи' ) self.log( f'!!ERROR!!\nIt\'s strange answer: "{ans}"') time.sleep(11.0 / len(check_list)) except Exception as e: self.log( '!! ERROR !!\nException in the monitor_apps. It stopped\n' + str(type(e)) + '\n' + str(e)) self.sender.report( '!! ERROR !!\nException in the monitor_apps. It stopped\n' + str(type(e)) + '\n' + str(e)) return def check_connection(self, app): if self.send_to_port('ping', app, 0.1, 32) == 'pong': self.log(f'App "{app.name}":{app.port} responded Pong') app.is_enabled = True return True else: if app.is_enabled == True: self.log(f'App "{app.name}":{app.port} is disabled') app.is_enabled = False return False def _start_(self, mode=0): if mode == 0: pass #quiet start elif mode == 1: self.sender.report('Бот запущен!') self.log('Bot is started. mode %d' % mode) elif mode == 2: self.sender.report('Бот перезапущен!') self.log('Bot is restarted %d' % mode) elif mode == 3: self.log('Bot is restarted %d' % mode) self.__listen__() def __listen__(self): try: self.__listener.listen() except requests.exceptions.ConnectionError: self.log('Connection ERROR in botbase') time.sleep(60) self._start_(3) except requests.exceptions.ReadTimeout: self.log('ReadTimeout (night reboot)') time.sleep(60) self._start_(3) except Exception as e: self.sender.report('Exception in Botbase:\n' + str(type(e)) + '\n' + str(e)) self.sender.report('Бот запустится через 5 секунд') self.log('!!ERROR!!\nException in Botbase:\n' + str(type(e)) + '\n' + str(e)) time.sleep(5) self._start_(2)
class Loader(Owner): def __init__(self, init_cfg: dict, init_state: dict, path: dict, sig: SignalHandlerDummy): self._sig = sig self.reload = False self._restore_filename = None self._lock = threading.Lock() self._stts_lock = threading.Lock() self._join_lock = threading.Lock() self._pub = PubSub() self._sig.set_wakeup_callback( lambda: self.sub_call('default', 'terminal_stop', True)) self._logger = logger.Logger(self) proxies.add_logger(self._logger.add('Proxy')) self._cfg = ConfigHandler(cfg=init_cfg, state=init_state, path=path, log=self._logger.add('CFG'), owner=self) self._logger.init(cfg=self._cfg, owner=self) self._log = self._logger.add('SYSTEM') self._listen = Listener(cfg=self._cfg, log=self._logger.add('REC'), owner=self) self._notifier = MajordomoNotifier(cfg=self._cfg, log=self._logger.add('Notifier'), owner=self) self._tts = stts.TextToSpeech(cfg=self._cfg, log=self._logger.add('TTS')) self._play = Player(cfg=self._cfg, log=self._logger.add('Player'), owner=self) self._music = music_constructor(cfg=self._cfg, logger=self._logger, owner=self) self._stt = stts.SpeechToText(cfg=self._cfg, log=self._logger.add('STT'), owner=self) self._mm = ModuleManager(cfg=self._cfg, log=self._logger.add('MM'), owner=self) self._updater = Updater(cfg=self._cfg, log=self._logger.add('Updater'), owner=self) self._backup = Backup(cfg=self._cfg, log=self._logger.add('Backup'), owner=self) self._terminal = MDTerminal(cfg=self._cfg, log=self._logger.add('Terminal'), owner=self) self._server = server_constructor(cfg=self._cfg, logger=self._logger, owner=self) self._plugins = Plugins(cfg=self._cfg, log=self._logger.add('Plugins'), owner=self) self._duplex_pool = DuplexPool(cfg=self._cfg, log=self._logger.add('DP'), owner=self) self._discovery = DiscoveryServer(cfg=self._cfg, log=self._logger.add('Discovery')) def start_all_systems(self): self._music.start() self._play.start() self._play.say_info(F( 'Приветствую. Голосовой терминал настраивается, три... два... один...' ), 0, wait=0.5) self._stt.start() self._cfg.start() self._notifier.start() self._mm.start() self._updater.start() self._terminal.start() self._server.start() self._discovery.start() self._backup.start() self._plugins.start() self.messenger( lambda: self.log(available_version_msg(self._cfg.version_info), logger.INFO), None) self.sub_call('default', 'version', self._cfg.version_str) self.volume_callback(self.get_volume()) def stop_all_systems(self): self._cfg.config_save(final=True) self.join_thread(self._plugins) self._mm.stop() self.join_thread(self._discovery) self.join_thread(self._server) self.join_thread(self._terminal) self.join_thread(self._backup) self.join_thread(self._updater) self.join_thread(self._notifier) self.join_thread(self._duplex_pool) self._play.quiet() self._play.kill_popen() self._play.say_info(F('Голосовой терминал завершает свою работу.')) self._stt.stop() self._play.stop() self.join_thread(self._music) if self._restore_filename: self._backup.restore(self._restore_filename) self._restore_filename = '' self.join_thread(self._logger.remote_log) self._pub.stopping = True self._logger.join() self._pub.join() self._pub.report() def log(self, msg: str, lvl=logger.DEBUG): self._log(msg, lvl) def join_thread(self, obj): def obj_log(msg_: str, lvl=logger.DEBUG): if log_present: obj.log(msg_, lvl) def diagnostic_msg() -> str: _call = getattr(obj, 'diagnostic_msg', None) return ' {}'.format(_call()) if callable(_call) else '' with self._join_lock: close_signal = getattr(obj, 'close_signal', None) if close_signal: close_signal() if not obj.work: return log_present = callable(getattr(obj, 'log', None)) obj.work = False obj_log('stopping...') stop_time = time.time() obj.join() stop_time = time.time() - stop_time if not obj.is_alive(): obj_log('stop.', logger.INFO) else: obj_log('stopping error.', logger.ERROR) name_ = '.'.join(getattr(obj.log, 'name', [''])) if log_present else None name_ = name_ or str(obj) msg = 'Thread \'{}\' stuck and not stopping in {}!{}'.format( name_, pretty_time(stop_time), diagnostic_msg()) self.log(msg, logger.ERROR) def subscribe(self, event, callback, channel='default') -> bool: return self._pub.subscribe(event, callback, channel) def unsubscribe(self, event, callback, channel='default') -> bool: return self._pub.unsubscribe(event, callback, channel) def registration(self, event: str, channel='default'): return self._pub.registration(event, channel) def has_subscribers(self, event: str, channel='default') -> bool: return self._pub.has_subscribers(event, channel) def events_list(self, channel='default') -> list: return self._pub.events_list(channel) def send_notify(self, event: str, *args, **kwargs): return self._pub.sub_call('default', event, *args, **kwargs) def sub_call(self, channel: str, event: str, *args, **kwargs): return self._pub.sub_call(channel, event, *args, **kwargs) @staticmethod def messenger(call, callback, *args, **kwargs) -> bool: return Messenger(call, callback, *args, **kwargs)() def insert_module(self, module) -> bool: return self._mm.insert_module(module) def extract_module(self, callback) -> bool: return self._mm.extract_module(callback) def insert_detectors(self, detector): detector = prepare_detectors(detector) if not detector: return def callback(): with self._lock: detectors.DETECTORS.update(detector) self.__reconfigure_terminal(detector) # noinspection PyTypeChecker self.terminal_call('callme', callback, save_time=False) def extract_detectors(self, detector): detector = prepare_detectors(detector, True) if not detector: return def callback(): with self._lock: [detectors.DETECTORS.pop(x, None) for x in detector] self.__reconfigure_terminal(detector) # noinspection PyTypeChecker self.terminal_call('callme', callback, save_time=False) def add_stt_provider(self, name: str, entrypoint) -> bool: with self._stts_lock: if name not in STT.PROVIDERS: STT.PROVIDERS[name] = entrypoint return True return False def remove_stt_provider(self, name: str): with self._stts_lock: try: return STT.PROVIDERS.pop(name) except KeyError: return None def add_tts_provider(self, name: str, entrypoint) -> bool: with self._stts_lock: if name not in TTS.PROVIDERS: TTS.PROVIDERS[name] = entrypoint return True return False def remove_tts_provider(self, name: str): with self._stts_lock: try: return TTS.PROVIDERS.pop(name) except KeyError: return None def tts_providers(self) -> list: with self._stts_lock: return list(TTS.PROVIDERS.keys()) def stt_providers(self) -> list: with self._stts_lock: return list(STT.PROVIDERS.keys()) def is_tts_provider(self, name: str) -> bool: return name in TTS.PROVIDERS def is_stt_provider(self, name: str) -> bool: return name in STT.PROVIDERS def plugins_status(self, state: str) -> dict: return self._plugins.status(state) def get_plugin(self, name: str) -> object: try: return self._plugins.modules[name] except KeyError: raise RuntimeError('Plugin \'{}\' not found'.format(name)) except Exception as e: raise RuntimeError('Error accessing to plugin \'{}\': {}'.format( name, e)) def list_notifications(self) -> list: return self._notifier.list_notifications() def add_notifications(self, events: list, is_self=False) -> list: return self._notifier.add_notifications(events, is_self) def remove_notifications(self, events: list) -> list: return self._notifier.remove_notifications(events) def say(self, msg: str, lvl: int = 2, alarm=None, wait=0, is_file: bool = False, blocking: int = 0): self._play.say(msg, lvl, alarm, wait, is_file, blocking) def play(self, file, lvl: int = 2, wait=0, blocking: int = 0): self._play.play(file, lvl, wait, blocking) def say_info(self, msg: str, lvl: int = 2, alarm=None, wait=0, is_file: bool = False): self._play.say_info(msg, lvl, alarm, wait, is_file) def set_lvl(self, lvl: int) -> bool: return self._play.set_lvl(lvl) def clear_lvl(self): self._play.clear_lvl() def quiet(self): self._play.quiet() def full_quiet(self): self._play.full_quiet() def really_busy(self) -> bool: return self._play.really_busy() @state_cache(interval=0.008) def noising(self) -> bool: return self._play.noising() def kill_popen(self): self._play.kill_popen() def listen(self, hello: str = '', deaf: bool = True, voice: bool = False) -> tuple: return self._stt.listen(hello, deaf, voice) def voice_record(self, hello: str or None, save_to: str, convert_rate=None, convert_width=None, limit=8): return self._stt.voice_record(hello, save_to, convert_rate, convert_width, limit) def voice_recognition(self, audio, quiet: bool = False, fusion=None) -> str: return self._stt.voice_recognition(audio, quiet, fusion) @property def max_mic_index(self) -> int: return self._stt.max_mic_index @max_mic_index.setter def max_mic_index(self, val: int): self._stt.max_mic_index = val @property def mic_index(self) -> int: return self._stt.get_mic_index() def phrase_from_files(self, files: list) -> tuple: return self._stt.phrase_from_files(files) def multiple_recognition(self, file_or_adata, providers: list) -> list: return self._stt.multiple_recognition(file_or_adata, providers) @property def sys_say_chance(self) -> bool: return self._stt.sys_say.chance def music_state(self) -> str: return self._music.state() def music_play(self, uri): self._music.play(uri) def music_pause(self, paused=None): self._music.pause(paused) @property def music_plays(self) -> bool: return self._music.plays @property def music_volume(self): return self._music.volume @music_volume.setter def music_volume(self, vol): self._music.volume = vol @property def music_real_volume(self): return self._music.real_volume @music_real_volume.setter def music_real_volume(self, vol): self._music.real_volume = vol @property def music_track_name(self) -> str or None: return self._music.get_track_name() def tts(self, msg, realtime: bool = True): return self._tts.tts(msg, realtime) def ask_again_callback(self): self._pub.call('ask_again') def voice_activated_callback(self): self._pub.call('voice_activated') def speech_recognized_callback(self, status: bool): if status and self._cfg.gts('alarm_recognized'): self.play(self._cfg.path['bimp']) self._pub.call( 'speech_recognized_{}success'.format('' if status else 'un')) def record_callback(self, start_stop: bool): self._pub.call('start_record' if start_stop else 'stop_record') def say_callback(self, start_stop: bool): self._pub.call('start_talking' if start_stop else 'stop_talking') def speech_recognized(self, start_stop: bool): self._pub.call('start_recognized' if start_stop else 'stop_recognized') def music_status_callback(self, status: str): self._pub.call('music_status', status if status is not None else 'error') def music_volume_callback(self, volume: int): self._pub.call('music_volume', volume if volume is not None else -1) def volume_callback(self, volume: int): self._pub.call('volume', volume) @property def srv_ip(self) -> str: return self._cfg['smarthome']['ip'] def update(self): self._updater.update() def manual_rollback(self): self._updater.manual_rollback() def backup_manual(self): self._backup.manual_backup() def backup_restore(self, filename: str): if not self._restore_filename and filename: self._restore_filename = filename self.die_in(3, reload=True) def backup_list(self) -> list: return self._backup.backup_list() def modules_tester(self, phrase: str, call_me=None, rms=None, model=None): return self._mm.tester(phrase, call_me, rms, model) def die_in(self, wait, reload=False): self.reload = reload self._sig.die_in(wait) @property def get_volume_status(self) -> dict: music_volume = self._music.real_volume return { 'volume': self.get_volume(), 'music_volume': music_volume if music_volume is not None else -1 } def terminal_call(self, cmd: str, data='', lvl: int = 0, save_time: bool = True): self._terminal.call(cmd, data, lvl, save_time) def terminal_listen(self) -> bool: return self._terminal.listening def recognition_forever(self, interrupt_check: callable, callback: callable): return self._listen.recognition_forever(interrupt_check, callback) def get_vad_detector(self, source_or_mic, vad_mode=None, vad_lvl=None, energy_lvl=None, energy_dynamic=None): return self._listen.get_vad_detector(source_or_mic, vad_mode, vad_lvl, energy_lvl, energy_dynamic) def detected_fake(self, text: str, rms=None, model=None, cb=None): self._listen.detected_fake(text, rms, model, cb) def listener_listen(self, r=None, mic=None, vad=None): return self._listen.listen(r, mic, vad) def background_listen(self): return self._listen.background_listen() def get_volume(self) -> int: control = self._cfg.gt('volume', 'line_out', '') card = self._cfg.gt('volume', 'card', 0) if not control or control == volume_.UNDEFINED: return -2 return volume_.get_volume(control, card) def set_volume(self, vol) -> int: control = self._cfg.gt('volume', 'line_out', '') card = self._cfg.gt('volume', 'card', 0) if not control or control == volume_.UNDEFINED: return -2 try: return volume_.set_volume(vol, control, card) except RuntimeError as e: self.log('set_volume({}): {}'.format(vol, e), logger.WARN) return -1 def settings_from_inside(self, cfg: dict) -> bool: with self._lock: return self._cfg.update_from_dict(cfg) def settings_from_srv(self, cfg: str or dict) -> dict: # Reload modules if their settings could be changes with self._lock: diff = self._cfg.update_from_external(cfg) reload_terminal = False detector_reconfigure = False vad_reconfigure = False if diff is None: self._cfg.print_cfg_no_change() return {} lang, lang_check = None, None if is_sub_dict('settings', diff) and ('lang' in diff['settings'] or 'lang_check' in diff['settings']): # re-init lang lang = diff['settings'].pop('lang', None) lang_check = diff['settings'].pop('lang_check', None) self._cfg.lang_init() if lang: # reload phrases self._stt.reload() # reload modules self._mm.reload() if is_sub_dict('models', diff): # reload models. Reload terminal - later self._cfg.models_load() reload_terminal = True if is_sub_dict('log', diff): # reload logger self._logger.reload() if is_sub_dict('cache', diff): # re-check tts cache self._cfg.tts_cache_check() if is_sub_dict('proxy', diff): # re-init proxy self._cfg.proxies_init() if is_sub_dict('music', diff): # reconfigure music server self.music_reload() if is_sub_dict('update', diff): # update 'update' interval self._updater.reload() if is_sub_dict('backup', diff): # update backup interval self._backup.reload() if is_sub_dict('smarthome', diff): if 'allow_addresses' in diff['smarthome']: # re-init allow ip addresses self._cfg.allow_addresses_init() if 'disable_server' in diff['smarthome']: # handle [smarthome] disable_server self.messenger(self.server_reload, None) # resubscribe self._notifier.reload(diff) self._duplex_pool.reload() if is_sub_dict('noise_suppression', diff): # reconfigure APM. Reload terminal - later self._cfg.apm_configure() reload_terminal = True if is_sub_dict('listener', diff): reload_terminal = True detector_reconfigure = 'detector' in diff['listener'] vad_reconfigure = bool([ key for key in ('vad_mode', 'vad_chrome') if key in diff['listener'] ]) if is_sub_dict('settings', diff) or reload_terminal: # reload terminal # noinspection PyTypeChecker self.terminal_call('reload', (detector_reconfigure, vad_reconfigure), save_time=False) # restore lang's if lang is not None: diff['settings']['lang'] = lang if lang_check is not None: diff['settings']['lang_check'] = lang_check # check and reload plugins self._plugins.reload(diff) self._cfg.print_cfg_change() self._cfg.config_save() return diff def music_reload(self): self._music = music_constructor(self._cfg, self._logger, self, self._music) def server_reload(self): self._server = server_constructor(self._cfg, self._logger, self, self._server) def __reconfigure_terminal(self, detector: set or dict): if self._cfg['listener'][ 'detector'] in detector or self._cfg.detector.NAME in detector: # noinspection PyProtectedMember self._terminal._reload((True, False))