import  asyncio 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								import  json 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								import  logging 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								import  os 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								import  ssl 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								import  uuid 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								import  time 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								from  common . basedir  import  BASEDIR 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								from  aiohttp  import  web 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								from  aiortc  import  RTCPeerConnection ,  RTCSessionDescription 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								import  cereal . messaging  as  messaging 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								from  tools . bodyteleop . bodyav  import  BodyMic ,  WebClientSpeaker ,  force_codec ,  play_sound ,  MediaBlackhole ,  EncodedBodyVideo 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								logger  =  logging . getLogger ( " pc " ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								logging . basicConfig ( level = logging . INFO ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								pcs  =  set ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								pm ,  sm  =  None ,  None 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								TELEOPDIR  =  f " { BASEDIR } /tools/bodyteleop " 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								async  def  index ( request ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  content  =  open ( TELEOPDIR  +  " /static/index.html " ,  " r " ) . read ( ) 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  now  =  time . monotonic ( ) 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  request . app [ ' mutable_vals ' ] [ ' last_send_time ' ]  =  now 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  request . app [ ' mutable_vals ' ] [ ' last_override_time ' ]  =  now 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  request . app [ ' mutable_vals ' ] [ ' prev_command ' ]  =  [ ] 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  request . app [ ' mutable_vals ' ] [ ' find_person ' ]  =  False 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  return  web . Response ( content_type = " text/html " ,  text = content ) 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								async  def  control_body ( data ,  app ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  now  =  time . monotonic ( ) 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  if  ( data [ ' type ' ]  ==  ' dummy_controls ' )  and  ( now  <  ( app [ ' mutable_vals ' ] [ ' last_send_time ' ]  +  0.2 ) ) : 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    return 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  if  ( data [ ' type ' ]  ==  ' control_command ' )  and  ( app [ ' mutable_vals ' ] [ ' prev_command ' ]  ==  [ data [ ' x ' ] ,  data [ ' y ' ] ]  and  data [ ' x ' ]  ==  0  and  data [ ' y ' ]  ==  0 ) : 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    return 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  logger . info ( str ( data ) ) 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  x  =  max ( - 1.0 ,  min ( 1.0 ,  data [ ' x ' ] ) ) 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  y  =  max ( - 1.0 ,  min ( 1.0 ,  data [ ' y ' ] ) ) 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  dat  =  messaging . new_message ( ' testJoystick ' ) 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  dat . testJoystick . axes  =  [ x ,  y ] 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  dat . testJoystick . buttons  =  [ False ] 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  pm . send ( ' testJoystick ' ,  dat ) 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  app [ ' mutable_vals ' ] [ ' last_send_time ' ]  =  now 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  if  ( data [ ' type ' ]  ==  ' control_command ' ) : 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    app [ ' mutable_vals ' ] [ ' last_override_time ' ]  =  now 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    app [ ' mutable_vals ' ] [ ' prev_command ' ]  =  [ data [ ' x ' ] ,  data [ ' y ' ] ] 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								async  def  dummy_controls_msg ( app ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  while  True : 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ' last_send_time '  in  app [ ' mutable_vals ' ] : 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      this_time  =  time . monotonic ( ) 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      if  ( app [ ' mutable_vals ' ] [ ' last_send_time ' ]  +  0.2 )  <  this_time : 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        await  control_body ( { ' type ' :  ' dummy_controls ' ,  ' x ' :  0 ,  ' y ' :  0 } ,  app ) 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    await  asyncio . sleep ( 0.2 ) 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								async  def  start_background_tasks ( app ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  app [ ' bgtask_dummy_controls_msg ' ]  =  asyncio . create_task ( dummy_controls_msg ( app ) ) 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								async  def  stop_background_tasks ( app ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  app [ ' bgtask_dummy_controls_msg ' ] . cancel ( ) 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  await  app [ ' bgtask_dummy_controls_msg ' ] 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								async  def  offer ( request ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  logger . info ( " \n \n \n newoffer! \n \n " ) 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  params  =  await  request . json ( ) 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  offer  =  RTCSessionDescription ( sdp = params [ " sdp " ] ,  type = params [ " type " ] ) 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  speaker  =  WebClientSpeaker ( ) 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  blackhole  =  MediaBlackhole ( ) 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  pc  =  RTCPeerConnection ( ) 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  pc_id  =  " PeerConnection( %s ) "  %  uuid . uuid4 ( ) 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  pcs . add ( pc ) 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  def  log_info ( msg ,  * args ) : 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    logger . info ( pc_id  +  "   "  +  msg ,  * args ) 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  log_info ( " Created for  %s " ,  request . remote ) 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  @pc . on ( " datachannel " ) 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  def  on_datachannel ( channel ) : 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    request . app [ ' mutable_vals ' ] [ ' remote_channel ' ]  =  channel 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    @channel . on ( " message " ) 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    async  def  on_message ( message ) : 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      data  =  json . loads ( message ) 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      if  data [ ' type ' ]  ==  ' control_command ' : 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        await  control_body ( data ,  request . app ) 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        times  =  { 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								          ' type ' :  ' ping_time ' , 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								          ' incoming_time ' :  data [ ' dt ' ] , 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								          ' outgoing_time ' :  int ( time . time ( )  *  1000 ) , 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        } 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        channel . send ( json . dumps ( times ) ) 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      if  data [ ' type ' ]  ==  ' battery_level ' : 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        sm . update ( timeout = 0 ) 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if  sm . updated [ ' carState ' ] : 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								          channel . send ( json . dumps ( { ' type ' :  ' battery_level ' ,  ' value ' :  int ( sm [ ' carState ' ] . fuelGauge  *  100 ) } ) ) 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      if  data [ ' type ' ]  ==  ' play_sound ' : 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        logger . info ( f " Playing sound:  { data [ ' sound ' ] } " ) 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        await  play_sound ( data [ ' sound ' ] ) 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      if  data [ ' type ' ]  ==  ' find_person ' : 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        request . app [ ' mutable_vals ' ] [ ' find_person ' ]  =  data [ ' value ' ] 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  @pc . on ( " connectionstatechange " ) 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  async  def  on_connectionstatechange ( ) : 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    log_info ( " Connection state is  %s " ,  pc . connectionState ) 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  pc . connectionState  ==  " failed " : 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      await  pc . close ( ) 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      pcs . discard ( pc ) 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  @pc . on ( ' track ' ) 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  def  on_track ( track ) : 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    logger . info ( f " Track received:  { track . kind } " ) 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  track . kind  ==  " audio " : 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      speaker . addTrack ( track ) 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    elif  track . kind  ==  " video " : 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      blackhole . addTrack ( track ) 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    @track . on ( " ended " ) 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    async  def  on_ended ( ) : 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      log_info ( " Remote  %s  track ended " ,  track . kind ) 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      if  track . kind  ==  " audio " : 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        await  speaker . stop ( ) 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      elif  track . kind  ==  " video " : 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        await  blackhole . stop ( ) 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  video_sender  =  pc . addTrack ( EncodedBodyVideo ( ) ) 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  force_codec ( pc ,  video_sender ,  forced_codec = ' video/H264 ' ) 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  _  =  pc . addTrack ( BodyMic ( ) ) 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  await  pc . setRemoteDescription ( offer ) 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  await  speaker . start ( ) 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  await  blackhole . start ( ) 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  answer  =  await  pc . createAnswer ( ) 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  await  pc . setLocalDescription ( answer ) 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  return  web . Response ( 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    content_type = " application/json " , 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    text = json . dumps ( 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      { " sdp " :  pc . localDescription . sdp ,  " type " :  pc . localDescription . type } 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    ) , 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  ) 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								async  def  on_shutdown ( app ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  coros  =  [ pc . close ( )  for  pc  in  pcs ] 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  await  asyncio . gather ( * coros ) 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  pcs . clear ( ) 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								async  def  run ( cmd ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  proc  =  await  asyncio . create_subprocess_shell ( 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    cmd , 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    stdout = asyncio . subprocess . PIPE , 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    stderr = asyncio . subprocess . PIPE 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  ) 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  stdout ,  stderr  =  await  proc . communicate ( ) 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  logger . info ( " Created key and cert! " ) 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  if  stdout : 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    logger . info ( f ' [stdout] \n { stdout . decode ( ) } ' ) 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  if  stderr : 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    logger . info ( f ' [stderr] \n { stderr . decode ( ) } ' ) 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								def  main ( ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  global  pm ,  sm 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  pm  =  messaging . PubMaster ( [ ' testJoystick ' ] ) 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  sm  =  messaging . SubMaster ( [ ' carState ' ,  ' logMessage ' ] ) 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  # App needs to be HTTPS for microphone and audio autoplay to work on the browser 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  cert_path  =  TELEOPDIR  +  ' /cert.pem ' 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  key_path  =  TELEOPDIR  +  ' /key.pem ' 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  if  ( not  os . path . exists ( cert_path ) )  or  ( not  os . path . exists ( key_path ) ) : 
 
							 
						 
					
						
							
								
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    asyncio . run ( run ( f ' openssl req -x509 -newkey rsa:4096 -nodes -out  { cert_path }  -keyout  { key_path }   \
  
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                     - days  365  - subj  " /C=US/ST=California/O=commaai/OU=comma body " ' )) 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  else : 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    logger . info ( " Certificate exists! " ) 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  ssl_context  =  ssl . SSLContext ( ) 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  ssl_context . load_cert_chain ( cert_path ,  key_path ) 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  app  =  web . Application ( ) 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  app [ ' mutable_vals ' ]  =  { } 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  app . on_shutdown . append ( on_shutdown ) 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  app . router . add_post ( " /offer " ,  offer ) 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  app . router . add_get ( " / " ,  index ) 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  app . router . add_static ( ' /static ' ,  TELEOPDIR  +  ' /static ' ) 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  app . on_startup . append ( start_background_tasks ) 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  app . on_cleanup . append ( stop_background_tasks ) 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  web . run_app ( app ,  access_log = None ,  host = " 0.0.0.0 " ,  port = 5000 ,  ssl_context = ssl_context ) 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								if  __name__  ==  " __main__ " : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  main ( )