class WakewordUploadThread(Thread): def __init__(self, host: str, port: int, zipPath: str): super().__init__() self._logger = Logger(prepend='[HotwordUploadThread]') self.setDaemon(True) self._host = host self._port = port self._zipPath = Path(zipPath) def run(self): try: wakewordName = self._zipPath.stem with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock: sock.bind((self._host, self._port)) self._logger.logInfo('Waiting for a device to connect') sock.listen() conn, addr = sock.accept() self._logger.logInfo( f'New device connected with address **{addr}**') with self._zipPath.open(mode='rb') as f: data = f.read(1024) while data: conn.send(data) data = f.read(1024) self._logger.logInfo( f'Waiting on a feedback from **{addr[0]}**') conn.settimeout(20) try: while True: answer = conn.recv(1024).decode() if not answer: raise Exception( 'The device closed the connection before confirming...' ) if answer == '0': self._logger.logInfo( f'Wakeword **{wakewordName}** upload to **{addr[0]}** success' ) break elif answer == '-1': raise Exception( 'The device failed downloading the hotword') elif answer == '-2': raise Exception( 'The device failed installing the hotword') except timeout: self._logger.logWarning( 'The device did not confirm the operation as successfull in time. The hotword installation might have failed' ) except Exception as e: self._logger.logError(f'Error uploading wakeword: {e}')
class HotwordDownloadThread(Thread): def __init__(self, host: str, port: int, hotwordName: str): super().__init__() self._logger = Logger(prepend='[HotwordDownloadThread]') self._host = host self._port = int(port) self._hotwordName = hotwordName self.setDaemon(True) def run(self): sock = None try: self._logger.logInfo('Cleaning up') rootPath = Path(SuperManager.getInstance().commons.rootDir(), 'hotwords') hotwordPath = rootPath / f'{self._hotwordName}' zipPath = hotwordPath.with_suffix('.zip') if zipPath.exists(): zipPath.unlink() if hotwordPath.exists(): shutil.rmtree(hotwordPath, ignore_errors=True) self._logger.logInfo( f'Connecting to **{self._host}_{self._port}**') sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.connect((self._host, self._port)) self._logger.logInfo( f'Receiving hotword package: **{self._hotwordName}**') sock.settimeout(2) try: with zipPath.open('wb') as f: while True: data = sock.recv(1024) if not data: break f.write(data) except socket.timeout: sock.settimeout(None) except Exception as e: self._logger.logError(f'Error downloading hotword: {e}') if sock: sock.send(b'-1') sock.close() return try: self._logger.logInfo('New hotword received, unpacking...') shutil.unpack_archive(filename=zipPath, extract_dir=hotwordPath) conf = SuperManager.getInstance( ).configManager.getSnipsConfiguration(parent='snips-hotword', key='model', createIfNotExist=True) if not isinstance(conf, list): conf = list() addSnips = True regex = re.compile(f'.*/{hotwordPath}=[0-9.]+$') copy = conf.copy() for i, hotword in enumerate(copy): if hotword.find('/snips_hotword='): addSnips = False elif regex.match(hotword): conf.pop(i) if addSnips: conf.append(str(rootPath / 'snips_hotword=0.53')) conf.append(f'{hotwordPath}=0.52') SuperManager.getInstance().configManager.updateSnipsConfiguration( parent='snips-hotword', key='model', value=conf, createIfNotExist=True) subprocess.run(['sudo', 'systemctl', 'restart', 'snips-satellite']) sock.send(b'0') self._logger.logInfo( f'Sucessfully installed new hotword **{self._hotwordName}**') except Exception as e: self._logger.logError( f'Error while unpacking and installing hotword: {e}') sock.send(b'-2') finally: sock.close() os.remove(zipPath)