def stop_servers(): logger = InfoLogger(__name__).get_logger() # logger.info('Servers to stop: %d' % len(Servers.server_threads)) for ins_name, thread in Servers.server_threads.iteritems(): thread.stop() logger.info('Stop server : %s' % ins_name)
class BaseConnection(object): def __init__(self, stream, address, delimiter): self.logger = InfoLogger(__name__).get_logger() self.name = self.__class__.__name__ self.delimiter = delimiter self._stream = stream self._address = address self._stream.set_close_callback(self.on_close) self.read_message() def read_message(self): # self.logger.info("In read_message, %r" % self.delimiter) self._stream.read_until(self.delimiter, self.on_message_read) def on_message_read(self, data): pass # def send_to_ws(self, data, robot_uid): # """Send to broswer through websocket""" # pass def on_close(self): self.logger.info('[%s] client close: %s' % (self.name, str(self._address)))
def run_video_feed(robot_uid, sock, func, handle): logger = InfoLogger(__name__).get_logger() logger.info('[Video] run_video_feed start') try: while True: try: select.select([], [sock], []) except socket.error: logger.info('[Video] socket shutdown') break # image_container = yield func(handle) image_container = func(handle) image_data_lst = format_image_data(image_container) image_uid = uuid.uuid4().hex for image_dct in image_data_lst: send_data = format_send_data(robot_uid, image_uid, image_dct) sock.sendall(send_data) # logger.info('[Video] run_video_feed done') except Exception as e: logger.info('[Video] run_video_feed error : %s' % e) logger.info('[Video] run_video_feed exit done')
def run_audio_stream(robot_uid, sock, proc): logger = InfoLogger(__name__).get_logger() logger.info('[Audio] run_audio_stream start') try: while True: if proc.poll(): break output = proc.stdout.read(ConfigAudio.buffer_size) try: select.select([], [sock], []) except socket.error: logger.info('[Audio] socket shutdown') break format_data = format_send_data(robot_uid, output) sock.sendall(format_data) # logger.info('[Audio] send output : %s' % format_data) except Exception as e: logger.info('[Audio] run_audio_stream error : %s' % e) if not proc.poll(): proc.terminate() # proc.kill() logger.info('[Audio] run_audio_stream exit done')
class BaseTCPServer(TCPServer): def __init__(self, port, connection): super(BaseTCPServer, self).__init__() self.name = self.__class__.__name__ self.logger = InfoLogger(self.name).get_logger() self.port = port self.connection = connection def handle_stream(self, stream, address): self.logger.info("[%s] new connection: %s %s" % (self.name, address, stream)) self.connection(stream, address) def start(self): try: self.logger.info("[%s] starting at port %s" % (self.name, self.port)) self.listen(self.port) self.logger.info("[%s] socket setup done" % self.name) ioloop = IOLoop() ioloop.current().start() except Exception as e: self.logger.info("[%s] start error: %s" % (self.name, e))
def start_server_thread(cls, server_ins): ins_name = server_ins.__class__.__name__ if ins_name in cls.server_threads: return thread = ServerThread(server_ins) thread.setName('Thread-%s' % ins_name) cls.server_threads[ins_name] = thread logger = InfoLogger(__name__).get_logger() logger.info('server_threads count : %d' % len(cls.server_threads)) thread.start()
class WebsocketServer(object): def __init__(self): self.logger = InfoLogger(__name__).get_logger() # self.ioloop = IOLoop() self.shell = ConfigSSH.local_ws_shell self.port = ConfigSSH.local_ws_port self.height = ConfigSSH.height self.width = ConfigSSH.width self.winheight = ConfigSSH.winheight self.winwidth = ConfigSSH.winwidth self.max_terminals = ConfigSSH.max_terminals self.running = False def start(self): self.logger.info('Starting websocket server') term_settings = { 'height': self.height, 'width': self.width, 'winheight': self.winheight, "winwidth": self.winwidth, } # term_manager = SingleTermManager(shell_command=[self.shell]) term_manager = UniqueTermManager(shell_command = [self.shell], \ max_terminals = self.max_terminals, term_settings = term_settings) handlers = [ # (r"/websocket", MyTermSocket, {'term_manager': term_manager}), # (r"/websocket", TermSocket, {'term_manager': term_manager}), (r"/websocket/([^/]*)", TermSocket, { 'term_manager': term_manager }), ] app = tornado.web.Application(handlers) app.listen(self.port) self.logger.info('Listen on port ' + str(self.port)) self.running = True self.logger.info('Start websocket server done') # self.ioloop.current().start() IOLoop.current().start() def stop(self): # self.ioloop.current().stop() IOLoop.current().stop() self.running = False self.logger.info('Stop websocket server done') def is_running(self): return self.running
def run_write_client(sock, ws_connect): logger = InfoLogger(__name__).get_logger() logger.info('[writer] start') ws = yield ws_connect while True: try: recv_sock = sock.recv(1024) # logger.info('[writer] recv_sock : %r' % recv_sock) if recv_sock: msg_list = recv_sock.split(ConfigSSH.delimiter) for msg_str in msg_list: # msg_str may be '', if json loads failed, continue to next one try: msg_dict = json.loads(msg_str) except: continue msg = msg_dict.get('msg', None) if msg: # yield ws.write_message(msg) ws.write_message(msg) # logger.info('[writer] write to ws : %r' % msg) else: logger.info('[writer] read no msg from sock : %r' % msg) else: # sock.shutdown(socket.SHUT_RDWR) is called logger.info('[writer] socket shutdown') # send to ws, let run_read_client know and exit ws.write_message(r'["stdin", "\r"]') break except Exception as e: logger.info('[writer] error: %s' % e) break logger.info('[writer] exit done')
def run_read_client(sock, ws_connect, robot_uid, term_id): logger = InfoLogger(__name__).get_logger() logger.info('[reader] start') ws = yield ws_connect pairs = SocketMap.pairs.get(term_id, None) if pairs: pairs['websocket'] = ws SocketMap.pairs[term_id] = pairs while True: try: msg = yield ws.read_message() # logger.info('[reader] ws.read_message : %r' % msg) # ws server may return None after UnicodeDecodeError raised # if msg is None: # break if msg: # make sure the socket is not closed try: select.select([], [sock], []) except socket.error: logger.info('[reader] socket shutdown') break sock_msg = format_sock_msg(robot_uid, term_id, msg) sock.sendall(sock_msg) # logger.info('[reader] send to sock : %r' % sock_msg) else: logger.info('[reader] read no msg from ws : %r' % msg) break except Exception as e: logger.info('[reader] error: %s' % e) # break continue logger.info('[reader] exit done')
class ServerThread(threading.Thread): def __init__(self, server_ins): super(ServerThread, self).__init__() self.server_ins = server_ins self._stop = threading.Event() self.logger = InfoLogger(__name__).get_logger() def stop(self): self._stop.set() def stopped(self): return self._stop.isSet() def run(self): thread_name = threading.currentThread().getName() server_name = self.server_ins.__class__.__name__ self.logger.info('[%s] Run server=%s' % (thread_name, server_name)) self.server_ins.start()
class PuppetWebSocketServer(object): def __init__(self): self.logger = InfoLogger(__name__).get_logger() self.host = ConfigWebSocket.host self.port = ConfigWebSocket.port def start(self): try: app = Application([ (r'/puppet', PuppetWebSocketHandler), (r'/puppet/ssh/([^/]*)', SSHWebSocketHandler), (r'/puppet/video/([^/]*)', VideoWebSocketHandler), (r'/puppet/audio/([^/]*)', AudioWebSocketHandler), ]) self.logger.info("PuppetWebSocket Handler setup done") if ConfigSSL.enable: app.listen(address=self.host, port=self.port, ssl_options={ "certfile": ConfigSSL.certfile, "keyfile": ConfigSSL.keyfile, }) else: app.listen(address=self.host, port=self.port) self.logger.info('Listening ws at ' + str(self.host) + ':' + str(self.port)) ioloop = IOLoop() ioloop.current().start() except Exception as e: self.logger.info("PuppetWebSocketServer start error: %s" % e)
def run_media_stream(robot_uid, ff_obj): logger = InfoLogger(__name__).get_logger() logger.info('[Media] run_media_stream start') try: ff_obj.run() except Exception as e: logger.info('[Media] run_media_stream error : %s' % e) logger.info('[Media] run_media_stream exit done')
class Manager(object): def __init__(self): self.pid_file = ConfigManager.pid_file self.logger = InfoLogger(__name__).get_logger() def set_pid(self, pid): with open(self.pid_file, 'a') as f: f.write(str(pid) + '\n') def get_pid(self): if not os.path.exists(self.pid_file): return [] pids = [ int(pid.rstrip('\n')) for pid in open(self.pid_file, 'r').readlines() ] return pids def kill_process(self, pid=None): if pid: pids = [pid] else: pids = self.get_pid() try: for pid in pids: self.logger.info("Stopping pid %s" % pid) try: os.kill(pid, signal.SIGTERM) except OSError, err: if err.errno == errno.ESRCH: self.logger.info("pid %s not running" % pid) continue self.logger.info("Stop pid %s done" % pid) # clear file with open(self.pid_file, 'w') as f: f.write('') return "Done" except OSError, err: # if err.errno == errno.ESRCH: # return "Not running" if err.errno == errno.EPERM: return "No permission to signal this process!" else: return "Unknown error"
def run_video_feed(func, handle, image_pipe): logger = InfoLogger(__name__).get_logger() logger.info('[Media] run_video_feed start') try: while not image_pipe.is_closed(): image_container = func(handle) image_pipe.write(image_container[6]) except Exception as e: logger.info('[Media] run_video_feed error : %s' % e) logger.info('[Media] run_video_feed exit done')
def run_audio_feed(proc, audio_pipe): logger = InfoLogger(__name__).get_logger() logger.info('[Media] run_audio_feed start') try: while not audio_pipe.is_closed(): # audio_pipe.write(proc.stdout.read(80)) audio_pipe.write(proc.stdout.readline()) except Exception as e: logger.info('[Media] run_audio_feed error : %s' % e) logger.info('[Media] run_audio_feed exit done')
class BaseHTTPServer(object): def __init__(self, port): self.name = self.__class__.__name__ self.logger = InfoLogger(self.name).get_logger() self.port = port def set_app(self, app_tup_lst): app = Application(app_tup_lst) self.logger.info("[%s] app setup done" % self.name) return app def set_server(self, app): server = HTTPServer(app) if ConfigSSL.enable: server = HTTPServer(app, ssl_options = { "certfile" : ConfigSSL.certfile, "keyfile" : ConfigSSL.keyfile, } ) else: server = HTTPServer(app) server.listen(self.port) return server def start(self, app_tup_lst): try: app = self.set_app(app_tup_lst) server = self.set_server(app) self.logger.info("[%s] listen at port: %s" % (self.name, str(self.port))) ioloop = IOLoop() ioloop.current().start() except Exception as e: self.logger.info("[%s] start error: %s" % (self.name, e))
def stop_servers(): logger = InfoLogger(__name__).get_logger() # logger.info('Servers to stop: %d' % len(Servers.server_threads)) for ins_name, thread in Servers.server_threads.iteritems(): thread.stop() logger.info('Stop server : %s' % ins_name) # ----------------------------------------- # Get args from shell # ----------------------------------------- if args.run: logger = InfoLogger(__name__).get_logger() logger.info('Start running Puppet servers') pid = os.getpid() manager = Manager() manager.set_pid(pid) start_servers() elif args.restart: logger = InfoLogger(__name__).get_logger() logger.info('Restart running Puppet servers') logger.info('Stopping Puppet servers') stop_servers()
def stop_servers(): logger = InfoLogger(__name__).get_logger() for server_name, thread in Servers.server_threads.items(): thread.stop() logger.info('Stop server : %s' % server_name)
# return "Not running" if err.errno == errno.EPERM: return "No permission to signal this process!" else: return "Unknown error" if args.run: logger = InfoLogger(__name__).get_logger() start_servers() pid = os.getpid() manager = Manager() result = manager.kill_process() logger.info('Stop clients : %s' % result) manager.set_pid(pid) client = Client() client.connect() elif args.restart: logger = InfoLogger(__name__).get_logger() stop_servers() logger.info('Stop servers done') manager = Manager() result = manager.kill_process() logger.info('Stop clients : %s' % result)
class Client(object): def __init__(self): self.server_host = ConfigServer.host self.server_port = ConfigServer.port self.delimiter = ConfigServer.delimiter self.timeout = ConfigServer.timeout self.reconnect_delta = ConfigServer.reconnect_delta self.collector_handle_delta = ConfigCollector.handle_delta self.logger = InfoLogger(__name__).get_logger() self.thread_stop = False self.collector = Collector() self.executor = Executor() def connect(self): self.logger.info('start connect') sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.settimeout(self.timeout) try: sock.connect((self.server_host, self.server_port)) self.logger.info('connect success') self.setup_threads(sock) except KeyboardInterrupt: self.logger.info('Got Ctrl+C, exiting...') self.stop_all_thread() self.disconnect(sock) except socket.timeout: self.logger.info('socket connect timeout, reconnect') self.reconnect() except socket.error as s_error: # [Errno 111] Connection refused: client is starting, server is down # [Errno 32] Broken pipe: client is running, server is down if s_error.errno in (errno.ECONNREFUSED, errno.EPIPE): self.logger.info('socket connect error, try to reconnect') self.logger.info(str(s_error)) self.reconnect() else: raise except Exception as e: self.logger.info('Client connect error: %s' % e) def disconnect(self, sock): try: sock.close() self.logger.info('disconnect done') except: # sock is not available pass def reconnect(self): try: self.logger.info('try to reconnect socket') self.stop_all_thread() time.sleep(self.reconnect_delta) self.connect() except Exception as e: self.logger.info('Client reconnect error: %s' % e) def setup_threads(self, sock): try: self.logger.info('Setup new threads') self.thread_stop = False collector_thread = threading.Thread( \ target = self.run_collector_thread, \ kwargs = {'sock' : sock, 'stop' : lambda: self.thread_stop}) executor_thread = threading.Thread( \ target = self.run_executor_thread, \ kwargs = {'sock' : sock, 'stop' : lambda: self.thread_stop}) collector_thread.daemon = False executor_thread.daemon = False collector_thread.start() executor_thread.start() while collector_thread.isAlive() or executor_thread.isAlive(): collector_thread.join(10) executor_thread.join(10) except Exception as e: self.logger.info('setup_threads error: %s' % e) def stop_all_thread(self): self.thread_stop = True def run_collector_thread(self, sock, stop): try: while 1: data = self.collect_data() sock.sendall(data) time.sleep(self.collector_handle_delta) if stop(): self.logger.info('collector stopped') break except socket.error as s_error: if s_error.errno == errno.EPIPE: self.logger.info('collector get broken pipe, stopped, try to reconnect') self.reconnect() elif s_error.errno == errno.ETIMEDOUT: self.logger.info('collector socket connect timeout, try to reconnect') self.reconnect() else: self.logger.info('run_collector_thread error: %s' % s_error) raise except Exception as e: self.logger.info('run_collector_thread error: %s' % e) def run_executor_thread(self, sock, stop): try: while 1: try: data = sock.recv(1024) except socket.timeout: if stop(): self.logger.info('executor stopped') break else: continue self.logger.info('Receive data : %r' % data) if data: res = self.executor.command_explain(data) if res: res_format = self.format_data(res) sock.sendall(res_format) else: # Server stopped, received an empty string self.logger.info('executor receive empty data from server, stopped') break except Exception as e: self.logger.info('run_executor_thread error: %s' % e) def collect_data(self): try: data = self.format_data(self.collector.combine_robot_info()) except Exception as e: self.logger.info('collect_data error: %s' % e) data = '' return data def format_data(self, data): return str(data) + self.delimiter
class ClientProxy(object): def __init__(self, robot_uid): self.logger = InfoLogger(__name__).get_logger() self.robot_uid = robot_uid self.running = False def start(self, term_id): try: sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.connect((ConfigSSH.sock_host, ConfigSSH.sock_port)) SocketMap.pairs.setdefault(term_id, { 'socket': sock, 'websocket': None }) self.logger.info('socket connect done') # socket init send, let cloud server know where the client comes from sock_init = format_sock_msg(self.robot_uid, term_id) sock.sendall(sock_init) # create ws connect here to make sure only a term socket is opened ws_connect = websocket_connect(ConfigSSH.local_ws + '/' + term_id) write_thread = threading.Thread( \ target = start_write_client, \ kwargs = {'sock' : sock, 'ws_connect' : ws_connect}) read_thread = threading.Thread( \ target = start_read_client, \ kwargs = {'sock' : sock, 'ws_connect' : ws_connect,\ 'robot_uid' : self.robot_uid, 'term_id' : term_id}) self.logger.info('read/write thread setup done') write_thread.start() read_thread.start() self.running = True self.logger.info('ClientProxy start done') except Exception as e: self.logger.info('ClientProxy.start error : %s' % e) def stop(self, term_id): sock = SocketMap.pairs.get(term_id, {}).get('socket', None) if sock: try: # shutdown will send '' to socket, # writer can cache and exit sock.shutdown(socket.SHUT_RDWR) sock.close() self.logger.info('stop socket done') except Exception as e: self.logger.info('stop socket error : %s' % e) else: self.logger.info('no socket to stop') ws = SocketMap.pairs.get(term_id, {}).get('websocket', None) if ws: ws.close() self.running = False self.logger.info('ClientProxy stop done') def is_running(self): return self.running def restart(self, term_id): self.stop(term_id) time.sleep(1) self.start(term_id)
class VideoFeedProxy(object): def __init__(self, robot_uid): self.logger = InfoLogger(__name__).get_logger() self.host = ConfigVideo.host self.port = ConfigVideo.port self.robot_uid = robot_uid self.sock = None def start(self, func, handle): try: sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.connect((self.host, self.port)) self.logger.info('video_feed socket setup done') self.sock = sock v_thread = threading.Thread( \ target = start_video_feed, \ kwargs = {'robot_uid' : self.robot_uid, 'sock' : sock, 'func' : func, 'handle' : handle}) v_thread.start() self.logger.info('VideoProxy start done') except Exception as e: self.logger.info('VideoProxy.start error : %s' % e) def stop(self): if self.sock: try: # shutdown will send '' to socket, # writer can cache and exit self.sock.shutdown(socket.SHUT_RDWR) self.sock.close() # self.sock = None self.logger.info('VideoProxy stop socket done') except Exception as e: self.logger.info('VideoProxy stop socket error : %s' % e) else: self.logger.info('VideoProxy no socket to stop') self.logger.info('VideoProxy stop done')
class Executor(object): def __init__(self): self.logger = InfoLogger(__name__).get_logger() self.sys_command = SystemCommand() self.behavior_command = BehaviorCommand() self.package_command = PackageCommand() self.video_command = VideoCommand() self.demo_command = DemoCommand() self.ssh_command = SSHCommand() self.audio_command = AudioCommand() self.media_command = MediaCommand() self.command_maps = ( self.sys_command, self.behavior_command, self.package_command, self.video_command, self.demo_command, self.ssh_command, self.audio_command, self.media_command, ) def get_command_func(self, command): # command_map = { # 'reboot' : self.sys_command.reboot, # 'shutdown' : self.sys_command.shutdown, # 'change_pw' : self.sys_command.change_pw, # 'change_name' : self.sys_command.change_name, # 'basic_awareness_enable' : self.sys_command.basic_awareness_enable, # 'basic_awareness_disable' : self.sys_command.basic_awareness_disable, # 'set_output_vol' : self.sys_command.set_output_vol, # 'rest' : self.sys_command.rest, # 'wake_up' : self.sys_command.wake_up, # 'count_off' : self.demo_command.count_off, # 'where_are_you' : self.demo_command.where_are_you, # } # return command_map.get(command, None) for command_cls in self.command_maps: if hasattr(command_cls, command): return getattr(command_cls, command) return None def command_explain(self, command_string): try: exec_szer = ExecutorSerializer() exec_obj = exec_szer.parse_from_string(command_string) command = exec_obj.executor.command args = exec_obj.executor.args origin = exec_obj.executor.origin self.logger.info('command: %s' % command) self.logger.info('args: %s' % str(args)) self.logger.info('origin: %s' % origin) res = None exception = None func = self.get_command_func(command) if func: taken_args = inspect.getargspec(func).args try: # taken_args : ['self', ...] if len(taken_args) > 1: res = func(args) else: res = func() self.logger.info('Command excuted') except Exception as e: self.logger.info('Executor run func error: %s' % e) exception = str(e) try: format_res = json.dumps(res) except: format_res = str(res) raiser_szer = RaiserSerializer() raiser_str = raiser_szer.dict_to_string({ 'command': command, 'args': args, 'origin': origin, 'response': format_res, 'exception': str(exception), }) self.logger.info('raiser_str: %r' % raiser_str) return raiser_str except Exception as e: self.logger.info('Executor command explain error: %s' % e)
class MediaStreamProxy(object): def __init__(self, robot_uid): self.logger = InfoLogger(__name__).get_logger() self.robot_uid = robot_uid self.host = ConfigMedia.host self.port = ConfigMedia.port self.path = ConfigMedia.path self.a_format = ConfigMedia.a_format self.analyze_duration = ConfigMedia.analyze_duration self.v_format = ConfigMedia.v_format self.pix_fmt = ConfigMedia.pix_fmt self.v_resolution = ConfigMedia.v_resolution self.audio_codec = ConfigMedia.audio_codec self.audio_bitrate = ConfigMedia.audio_bitrate self.strict_lvl = ConfigMedia.strict_lvl self.video_bitrate = ConfigMedia.video_bitrate self.output_format = ConfigMedia.output_format self.a_proc = None self.v_thread = None self.a_thread = None self.ff = None self.m_thread = None self.image_pipe = None self.audio_pipe = None def start(self, func, handle, bit_dict=None): try: self.image_pipe = ImagePipe() self.audio_pipe = AudioPipe() # Video thread self.v_thread = threading.Thread( \ target = run_video_feed, \ kwargs = {'func' : func, 'handle' : handle, 'image_pipe' : self.image_pipe}) # Pipe for media stream audio_pipe_r = self.audio_pipe.get_read_pipe() image_pipe_r = self.image_pipe.get_read_pipe() audio_input = 'pipe:%s' % str(audio_pipe_r) image_input = 'pipe:%s' % str(image_pipe_r) # Cover bitrate config from args if bit_dict: self.audio_bitrate = bit_dict.get('audio_bitrate') self.video_bitrate = bit_dict.get('video_bitrate') # -re (input) : Read input at native frame rate. # Set analyzeduration to 0 for audio to disable analyze delay audio_args = '-f {f} -analyzeduration {ad} -re'.format( f = self.a_format, ad = self.analyze_duration) image_args = '-f {f} -pix_fmt {pf} -s:v {sv} -re'.format( f = self.v_format, pf = self.pix_fmt, sv = self.v_resolution) # For dev # receiver = '/tmp/test.flv' # if os.path.exists(receiver): # os.unlink(receiver) receiver = 'rtmp://' + self.host + ':' + str(self.port) + \ self.path + str(self.robot_uid) # -c:a : audio codec, must be set in output # -b:a : audio bitrate # -b:v : video bitrate # output total bitrate = (video bitrate + audio bitrate)kbits/s # -muxdelay seconds : Set the maximum demux-decode delay. # -muxpreload seconds : Set the initial demux-decode delay. receiver_args = """-map 0 -c:a {ca} -strict -{s} -b:a {ba} -map 1 -b:v {bv} -f {f} -muxdelay 0.1 -muxpreload 0""".\ format(ca = self.audio_codec, s = self.strict_lvl, ba = self.audio_bitrate, bv = self.video_bitrate, f = self.output_format) ff_input = OrderedDict( [ (audio_input, audio_args), (image_input, image_args), ] ) ff_output = {receiver : receiver_args,} self.ff = ffmpy.FFmpeg(inputs = ff_input, outputs = ff_output) self.logger.info('[MediaStreamProxy] ff.cmd : %s' % self.ff.cmd) self.m_thread = threading.Thread( \ target = run_media_stream, \ kwargs = {'robot_uid' : self.robot_uid, 'ff_obj' : self.ff}) # Audio related # Do not use stdout=PIPE or stderr=PIPE with this function as # that can deadlock based on the child process output volume. # Use Popen with the communicate() method when you need pipes. a_command = 'arecord -f cd -t {a_format}'.format(a_format = self.a_format) self.a_proc = subprocess.Popen(shlex.split(a_command), \ stdout = self.audio_pipe.get_write_pipe()) self.m_thread.start() self.v_thread.start() self.logger.info('[MediaStreamProxy] start done') except Exception as e: self.logger.info('[MediaStreamProxy] start error : %s' % e) def stop(self): try: # Close working pipes if self.image_pipe: self.image_pipe.close() self.logger.info('[MediaStreamProxy] close image_pipe done') if self.audio_pipe: self.audio_pipe.close() self.logger.info('[MediaStreamProxy] close audio_pipe done') # Stop audio process if self.a_proc: self.a_proc.terminate() # self.a_proc.kill() # Use wait() to terminate the defunct process self.a_proc.wait() self.logger.info('[MediaStreamProxy] stop audio proc done') # Stop ffmpeg process if self.ff: self.ff.process.terminate() # self.ff.process.kill() self.logger.info('[MediaStreamProxy] stop ffmpeg proc done') except Exception as e: self.logger.info('[MediaStreamProxy] stop error : %s' % e) self.logger.info('[MediaStreamProxy] stop done')
class AudioStreamProxy(object): def __init__(self, robot_uid=None): self.logger = InfoLogger(__name__).get_logger() self.host = ConfigAudio.host self.port = ConfigAudio.port self.file_type = ConfigAudio.file_type self.rate = ConfigAudio.rate self.robot_uid = robot_uid self.sock = None self.proc = None def start(self): try: sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.connect((self.host, self.port)) self.logger.info('audio_stream socket setup done') self.sock = sock command = 'arecord -t {file_type} -r {rate}'.\ format(file_type = self.file_type, rate = self.rate) proc = subprocess.Popen(shlex.split(command), stdout=subprocess.PIPE) self.proc = proc a_thread = threading.Thread( \ target = run_audio_stream, \ kwargs = {'robot_uid' : self.robot_uid, 'sock' : sock, 'proc' : proc}) a_thread.start() # multiple client read one proc at the same time? self.logger.info('AudioStreamProxy start done') except Exception as e: self.logger.info('AudioStreamProxy.start error : %s' % e) def stop(self): if self.proc: try: self.proc.terminate() # self.proc.kill() self.logger.info('AudioStreamProxy stop proc done') except Exception as e: self.logger.info('AudioStreamProxy stop proc error : %s' % e) if self.sock: try: # shutdown will send '' to socket, # writer can cache and exit self.sock.shutdown(socket.SHUT_RDWR) self.sock.close() # self.sock = None self.logger.info('AudioStreamProxy stop socket done') except Exception as e: self.logger.info('AudioStreamProxy stop socket error : %s' % e) else: self.logger.info('AudioStreamProxy no socket to stop') self.logger.info('AudioStreamProxy stop done')