def _connect(self, username, session): if self._thread is None: _logger.log('Octoprint Socket: Connecting') def _on_message(ws, message): # _logger.log('Octoprint socket message recieved: %s' % message) self._callback.on_event(event=message) def _on_error(ws, error): _logger.log('Octoprint Socket Error: %s' % error) def _on_close(ws): _logger.log('Octoprint Socket: Ws Closed') self._callback.disconnected() def _on_open(ws): _logger.log('Octoprint Socket: Ws Opened') self._ws.send( _json.dumps({'auth': '%s:%s' % (username, session)})) self._ws.send(_json.dumps({'throttle': 10})) self._callback.connected() try: self._ws = websocket.WebSocketApp( "ws://localhost:5000/sockjs/websocket", on_message=_on_message, on_error=_on_error, on_close=_on_close, on_open=_on_open) self._thread = threading.Thread(target=self._ws.run_forever) self._thread.daemon = True self._thread.start() except Exception as e: _logger.warn(e)
def __init__(self, janus_url, port, machine, system, is_raspberry=False): self._url = "rtp://%s:%d?pkt_size=1300" % (janus_url, port) self._callback = None self._process = None self._vcodec = 'libx264' if not is_raspberry else 'h264_omx' self._shutting_down = False self._flip_horizontally = False self._flip_vertically = False self._rotate_90_clockwise = False self._enabled = False self._extra_arguments = {'s': '640x480', 'b:v': 500000} if system == 'Linux': if machine == 'armv7l': self._ffmpeg_dir = os.path.join(config.FFMPEG_DIR, 'linux', 'armv7l', 'ffmpeg') else: self._ffmpeg_dir = os.path.join(config.FFMPEG_DIR, 'linux', 'x86_64', 'ffmpeg') self._extra_arguments['preset'] = 'medium' self._extra_arguments['crf'] = 17 self._extra_arguments['tune'] = 'zerolatency' self._enabled = True os.system("chmod -R 777 %s" % config.FFMPEG_DIR) else: self._ffmpeg_dir = None _logger.log('Unable to start ffmpeg on %s system' % system)
def connect(self): if self._enabled: _logger.log('Janus: Connecting') def _on_error(ws, error): _logger.log('Janus Error: %s' % error) def _on_message(ws, msg): self._process_msg(msg) def _on_close(ws): _logger.log('Janus: Ws Closed') self._callback.disconnected() def _on_open(ws): _logger.log('Janus: Ws Opened') self._create_session() try: self._ws = websocket.WebSocketApp( self._url, on_open=_on_open, on_message=_on_message, on_close=_on_close, on_error=_on_error, subprotocols=['janus-protocol']) self._ws_thread = threading.Thread(target=self._ws.run_forever) self._ws_thread.daemon = True self._ws_thread.start() except Exception as e: _logger.warn(e)
def __init__(self, machine, system, ports, callback=None): _logger.log('Janus Socket: Initializing') # websocket.enableTrace(True) self._janus_ws_port = ports[0] self._janus_api_port = ports[1] self._janus_video_port = ports[2] self._url = 'ws://%s:%d/' % (config.JANUS_HOST, self._janus_ws_port) self._janus_thread = None self._janus_proc = None self._ws = None self._ws_thread = None self._transaction = None self._session_id = None self._handle_id = None self._paused = False self._streams = [] self._callback = callback self._stream_on_start = False self._enabled = False self._started_at = None if system == 'Linux': if machine == 'armv7l': self._janus_dir = os.path.join(config.JANUS_DIR, 'linux', 'armv7l') else: self._janus_dir = os.path.join(config.JANUS_DIR, 'linux', 'x86_64') self._enabled = True os.system("chmod -R 777 %s" % config.JANUS_DIR) else: self._janus_dir = None _logger.log('Unable to start janus on %s system' % system)
def start(self, url=None, flip_horizontally=False, flip_vertically=False, rotate_90_clockwise=False): if self._enabled: if not self._process: self._flip_horizontally = flip_horizontally self._flip_vertically = flip_vertically self._rotate_90_clockwise = rotate_90_clockwise self._shutting_down = False url = url if url else 'http://localhost:8080/?action=stream' try: _logger.log(url) code = urlopen(url).getcode() except Exception: code = 404 if code == 200: self._stream_from_url(url=url) else: self._stream_from_device() self.monitor(self._process)
def user_joined(data): _logger.log('Plabric Socket: User joined') if self._callback: data = _json.loads(data) if isinstance(data, str) else data user_nick = data['user_nick'] octoprint_api_key = data['octoprint_api_key'] self._callback.on_user_joined(user_nick, octoprint_api_key)
def start_video_stream(self): _logger.log('Janus: Start video stream') if not self.ws_connected(): self._stream_on_start = True self.connect() else: self._start_streams(self._streams[0])
def on_startup(self, host, port): _logger.log('On Plabric Startup') self._host = host self._port = port self._main = Main(self) if self._main.plabric_api_key: self._main.start()
def disconnect(self): self.set_loading(True) _logger.log('Disconnecting Plabric Plugin') self.video_streamer.stop() self.octoprint_socket.disconnect() self.plabric_socket.disconnect() self.plabric_webrtc.disconnect() self.set_step(Step.LOGIN_NEEDED) self.set_loading(False)
def save_setting(self, key, value): s = self.get_saved_settings() _logger.log('Saved key: %s - %s' % (key, value)) if s is None: s = {} s[key] = value config_path = self._plugin.get_plugin_data_folder() + "/.config.yaml" with open(config_path, 'w+') as outfile: yaml.dump(s, outfile, default_flow_style=False)
def start_video_stream(self): _logger.log('Janus: Start video stream') if time.time() - self._started_at < 4: time.sleep(4) if not self.ws_connected(): self._stream_on_start = True self.connect() else: self._start_streams(self._streams[0])
def stop_video_stream(self): _logger.log('Janus: Stop video stream') if self.ws_connected(): self._paused = True body = {'request': 'pause', 'id': self._streams[0]['id']} self._send_msg(body=body, transaction='stop_stream_%d' % self._streams[0]['id']) self._callback.video_stream_paused()
def clear_setting(self, key): s = self.get_saved_settings() _logger.log('Clear key: %s' % key) if s is None: return if key in s: s.pop(key) config_path = self._plugin.get_plugin_data_folder() + "/.config.yaml" with open(config_path, 'w+') as outfile: yaml.dump(s, outfile, default_flow_style=False)
def _attach_plugin(self): _logger.log('Janus: Attaching plugin') data = _json.dumps({ 'janus': 'attach', 'transaction': 'attach_plugin', 'session_id': self._session_id, 'plugin': 'janus.plugin.streaming', 'request': 'list' }) self._send_to_janus(data)
def connect(self): try: if not self._sio.connected and not self._connecting: self._connecting = True _logger.log('Plabric Socket: Connecting') self._sio.connect(self._domain, namespaces=[config.PLABRIC_SOCKET_NAMESPACE]) except (socketio.exceptions.ConnectionError, ValueError) as e: _logger.warn(e) self._connecting = False self._callback.on_connection_error()
def start(self, from_oauth=False): _logger.log('Starting') self.set_error('') if from_oauth and not self.plabric_api_key: f = self.probe_plugin_appkeys else: f = self.connect self._thread = threading.Thread(target=f) self._thread.daemon = True self._thread.start()
def __init__(self, domain, callback): _logger.log('Plabric Socket: Initializing') self._domain = domain self._sio = socketio.Client( reconnection=False, logger=False, ) self._add_event_handlers() self._callback = callback self._t = None self._connecting = False
def on_answer_received(self, json): _logger.log('Janus: Answer received') jsep = {'type': 'answer', 'sdp': json['sdp']} data = _json.dumps({ 'janus': 'message', 'transaction': 'on_answer_received', 'session_id': self._session_id, 'handle_id': self._handle_id, 'body': {}, 'jsep': jsep }) self._send_to_janus(data)
def on_ice_candidate_received(self, json): _logger.log('Janus: Ice candidate received') candidate = { 'sdpMid': json["id"], 'sdpMlineIndex': json["label"], 'candidate': json['candidate'] } data = _json.dumps({ 'janus': 'trickle', 'transaction': 'on_ice_candidate_received', 'session_id': self._session_id, 'handle_id': self._handle_id, 'candidate': candidate }) self._send_to_janus(data)
def set_step(self, step): self.step = step self.plugin.update_ui_status() if step == Step.ERROR_CONNECTION and not self._waiting_for_reconnect: _logger.log('Retry connection in %d seconds' % self.retry_time) self._waiting_for_reconnect = True thread = threading.Thread(target=self.retry_in_seconds, args=(self.retry_time, )) thread.daemon = True thread.start() if step == Step.CONNECTED or step == Step.READY: self.retry_time = randrange(30, 120)
def set_step(self, step): self.step = step self.plugin.update_ui_status() if step == Step.ERROR_CONNECTION and not self._waiting_for_reconnect and self._auto_reconnect: seconds = randrange(60, 300) _logger.log('Retry connection in %d seconds' % seconds) self._waiting_for_reconnect = True time.sleep(seconds) self._waiting_for_reconnect = False if self.step == Step.ERROR_CONNECTION: self.plabric_socket.disconnect() self.plabric_socket = None self._init_plabric_socket() self.connect()
def upload_file(self, data, file_path, callback): _logger.log('Octoprint API: Uploading file') action = DataAction(raw=data) file_name = data['params']['file_name'] _logger.log('%s Post file on: %s' % (self._name, self._get_url(action.path))) files = { "file": ("%s.gcode" % file_name, open(file_path, "rb").read()) } payload = {'path': 'plabric/tmp', 'select': 'true', 'print': 'false'} self._execute( requests.post(self._get_url(action.path), data=payload, files=files, headers={'X-Api-Key': self._api_key}), callback)
def execute_dowload(self, url, destination, callback): _logger.log('Plabric API: Downloading file') r = requests.get(url, stream=True) if r.status_code == 200: with open(destination, 'wb') as f: total_size = int(r.headers.get('content-length', 0)) if total_size is None: f.write(r.content) else: dl = 0 for data in r.iter_content(chunk_size=4096): dl += len(data) f.write(data) callback.on_succeed(None) else: callback.on_error(r.status_code)
def configure(self, json_servers): if not self._enabled: return _logger.log('Janus: Configuring') self._json_servers = json_servers stun_server = None stun_port = None turn_server = None turn_port = None turn_username = None turn_credential = None for s in json_servers: if 'username' in s and 'credential' in s: if not turn_server: turn_server, turn_port = s['urls'][0].replace( 'turn:', '').split(":") turn_username = s['username'] turn_credential = s['credential'] else: if not stun_server: stun_server, stun_port = s['urls'][0].replace( 'stun:', '').split(":") self._process_config_file(name='janus', params={ 'JANUS_DIR': self._janus_dir, 'TURN_SERVER': turn_server, 'TURN_PORT': turn_port, 'TURN_USERNAME': turn_username, 'TURN_CREDENTIAL': turn_credential, 'STUN_SERVER': stun_server, 'STUN_PORT': stun_port }) self._process_config_file( name='janus.transport.http', params={'JANUS_API_PORT': self._janus_api_port}) self._process_config_file( name='janus.transport.websockets', params={'JANUS_WS_PORT': self._janus_ws_port}) self._process_config_file( name='janus.plugin.streaming', params={'JANUS_VIDEO_PORT': self._janus_video_port}) self._run_janus()
def request_app_token(self): _logger.log('Octoprint API: Request app token') self.set_loading(True) class Response(APIProtocol): def __init__(self, p): self._p = p def on_succeed(self, data): self._p.polling_for_api_key(token=data['app_token']) def on_error(self, error): self._p.set_error(error) self._p.disconnect() self.set_step(Step.OCTOPRINT_OAUTH) self.octoprint_api.request_app_token(callback=Response(self))
def disconnect(self): _logger.log('Janus: Disconnecting') if self._ws: self._ws.close() self._ws.keep_running = False self._ws_thread = None self._ws = None self._paused = False self._stream_on_start = False if self._janus_proc: try: self._janus_proc.terminate() except Exception as e: _logger.warn(e) self._janus_thread = None
def probe_plugin_appkeys(self): _logger.log('Octoprint API: Probe plugin appkeys') self.set_loading(True) class Response(APIProtocol): def __init__(self, p): self._p = p def on_succeed(self, data): self._p.request_app_token() def on_error(self, error): self._p.set_error( 'You have to install Application Keys Plugin for grant access to Plabric or update your Octoprint version to version >= 1.3.10' ) self._p.disconnect() self.set_step(Step.OCTOPRINT_OAUTH) self.octoprint_api.probe_plugin_appkeys(callback=Response(self))
def connect(self): if self._enabled and not self.ws_connected(): _logger.log('Janus: Connecting') def _on_error(ws, error): _logger.log('Janus Error: %s' % error) self._reset_janus_ws() def _on_message(ws, msg): self._process_msg(msg) def _on_close(ws): _logger.log('Janus: Ws Closed') self._callback.disconnected() self._reset_janus_ws() def _on_open(ws): _logger.log('Janus: Ws Opened') self._create_session() try: if self._janus_thread is None: self._run_janus() if self._started_at is not None and time.time( ) - self._started_at < 4: time.sleep(2) self._ws = websocket.WebSocketApp( self._url, on_open=_on_open, on_message=_on_message, on_close=_on_close, on_error=_on_error, subprotocols=['janus-protocol']) _ws_thread = threading.Thread(target=self._ws.run_forever) _ws_thread.daemon = True _ws_thread.start() except Exception as e: _logger.warn(e)
def _process_config_file(self, name, params): janus_conf_template = os.path.join(self._janus_dir, 'etc/janus/%s.jcfg.template' % name) janus_conf_path = os.path.join(self._janus_dir, 'etc/janus/%s.jcfg' % name) if not os.path.isfile(janus_conf_template): _logger.log('Janus: Config file not found: %s' % janus_conf_template) return with open(janus_conf_template, "rt") as fin: with open(janus_conf_path, "wt") as fout: for line in fin: if len(line) > 0: for key, value in params.items(): if key in line: if value is None: line = ' #%s' % line else: line = line.replace( '{%s}' % key, str(value)) fout.write(line)
def _process_msg(self, msg): json = _json.loads(msg) if json['janus'] == 'ack': return _logger.log('Janus msg: %s' % json) if json['janus'] == 'success': if json['transaction'] == 'create': self._session_id = json['data']['id'] self._attach_plugin() elif json['transaction'] == 'attach_plugin': self._handle_id = json['data']['id'] self._send_to_janus( data=_json.dumps({ 'janus': 'keepalive', 'transaction': 'keepalive', 'session_id': self._session_id })) self._update_streams_list() elif json['transaction'] == 'update_streams_list': self._streams = json['plugindata']['data']['list'] if self._stream_on_start: self.start_video_stream() if json['janus'] == 'event': if 'jsep' in json: self._send_session_description(json['jsep']['type'], json['jsep']['sdp']) if json['janus'] == 'hangup': _logger.log('Disconnected WebRTC') self._callback.wrtc_disconnected() if json['janus'] == 'webrtcup': _logger.log('Connected WebRTC') self._callback.wrtc_connected() if json['janus'] == 'event': if 'plugindata' in json and 'data' in json[ 'plugindata'] and 'streaming' in json['plugindata']['data']: if json['plugindata']['data']['streaming'] == 'event': if 'result' in json['plugindata']['data']: if json['plugindata']['data']['result'][ 'status'] == 'started': self._callback.video_stream_started()