# include  <cassert> 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  <iostream> 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  <QFile> 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  <QDebug> 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								# include  <QVBoxLayout> 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  <QLabel> 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  <QJsonDocument> 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  <QJsonObject> 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  <QNetworkAccessManager> 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  <QNetworkRequest> 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  <QCryptographicHash> 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  <openssl/rsa.h> 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  <openssl/bio.h> 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  <openssl/pem.h> 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  "drive_stats.hpp" 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  "common/params.h" 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								# include  "common/util.h" 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								constexpr  double  MILE_TO_KM  =  1.60934 ; 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# if defined(QCOM) || defined(QCOM2) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								const  std : : string  private_key_path  =  " /persist/comma/id_rsa " ; 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# else 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								const  std : : string  private_key_path  =  util : : getenv_default ( " HOME " ,  " /.comma/persist/comma/id_rsa " ,  " /persist/comma/id_rsa " ) ; 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# endif 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								QByteArray  rsa_sign ( QByteArray  data )  { 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  auto  file  =  QFile ( private_key_path . c_str ( ) ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  bool  r  =  file . open ( QIODevice : : ReadOnly ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  assert ( r ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  auto  key  =  file . readAll ( ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  BIO  * mem  =  BIO_new_mem_buf ( key . data ( ) ,  key . size ( ) ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  assert ( mem ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  RSA  * rsa_private  =  PEM_read_bio_RSAPrivateKey ( mem ,  NULL ,  NULL ,  NULL ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  assert ( rsa_private ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  auto  sig  =  QByteArray ( ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  sig . resize ( RSA_size ( rsa_private ) ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  unsigned  int  sig_len ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  int  ret  =  RSA_sign ( NID_sha256 ,  ( unsigned  char * ) data . data ( ) ,  data . size ( ) ,  ( unsigned  char * ) sig . data ( ) ,  & sig_len ,  rsa_private ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  assert ( ret  = =  1 ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  assert ( sig_len  = =  sig . size ( ) ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  BIO_free ( mem ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  RSA_free ( rsa_private ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  return  sig ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								} 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								QString  create_jwt ( QString  dongle_id ,  int  expiry = 3600 )  { 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  QJsonObject  header ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  header . insert ( " alg " ,  " RS256 " ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  header . insert ( " typ " ,  " JWT " ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  auto  t  =  QDateTime : : currentSecsSinceEpoch ( ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  QJsonObject  payload ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  payload . insert ( " identity " ,  dongle_id ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  payload . insert ( " nbf " ,  t ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  payload . insert ( " iat " ,  t ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  payload . insert ( " exp " ,  t  +  expiry ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  QString  jwt  = 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    QJsonDocument ( header ) . toJson ( QJsonDocument : : Compact ) . toBase64 ( )  + 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    ' . '  + 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    QJsonDocument ( payload ) . toJson ( QJsonDocument : : Compact ) . toBase64 ( ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  auto  hash  =  QCryptographicHash : : hash ( jwt . toUtf8 ( ) ,  QCryptographicHash : : Sha256 ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  auto  sig  =  rsa_sign ( hash ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  jwt  + =  ' . '  +  sig . toBase64 ( ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  return  jwt ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								} 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								QLayout  * build_stat ( QString  name ,  int  stat )  { 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  QVBoxLayout  * layout  =  new  QVBoxLayout ; 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  QLabel  * metric  =  new  QLabel ( QString ( " %1 " ) . arg ( stat ) ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  metric - > setStyleSheet ( R " ( 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    font - size :  72 px ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    font - weight :  700 ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  ) " ); 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  layout - > addWidget ( metric ,  0 ,  Qt : : AlignLeft ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  QLabel  * label  =  new  QLabel ( name ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  label - > setStyleSheet ( R " ( 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    font - size :  32 px ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    font - weight :  600 ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  ) " ); 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  layout - > addWidget ( label ,  0 ,  Qt : : AlignLeft ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  return  layout ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								} 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								void  DriveStats : : replyFinished ( QNetworkReply  * l )  { 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  QString  answer  =  l - > readAll ( ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  answer . chop ( 1 ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  QJsonDocument  doc  =  QJsonDocument : : fromJson ( answer . toUtf8 ( ) ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  if  ( doc . isNull ( ) )  { 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    qDebug ( )  < <  " JSON Parse failed " ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  QString  IsMetric  =  QString : : fromStdString ( Params ( ) . get ( " IsMetric " ) ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  bool  metric  =  ( IsMetric  = = " 1 " ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  QJsonObject  json  =  doc . object ( ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  auto  all  =  json [ " all " ] . toObject ( ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  auto  week  =  json [ " week " ] . toObject ( ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  QGridLayout  * gl  =  new  QGridLayout ( ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  int  all_distance  =  all [ " distance " ] . toDouble ( ) * ( metric  ?  MILE_TO_KM  :  1 ) ; 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								  gl - > addWidget ( new  QLabel ( " ALL TIME " ) ,  0 ,  0 ,  1 ,  3 ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  gl - > addLayout ( build_stat ( " DRIVES " ,  all [ " routes " ] . toDouble ( ) ) ,  1 ,  0 ,  3 ,  1 ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  gl - > addLayout ( build_stat ( metric  ?  " KM "  :  " MILES " ,  all_distance ) ,  1 ,  1 ,  3 ,  1 ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  gl - > addLayout ( build_stat ( " HOURS " ,  all [ " minutes " ] . toDouble ( )  /  60 ) ,  1 ,  2 ,  3 ,  1 ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  int  week_distance  =  week [ " distance " ] . toDouble ( ) * ( metric  ?  MILE_TO_KM  :  1 ) ; 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								  gl - > addWidget ( new  QLabel ( " PAST WEEK " ) ,  6 ,  0 ,  1 ,  3 ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  gl - > addLayout ( build_stat ( " DRIVES " ,  week [ " routes " ] . toDouble ( ) ) ,  7 ,  0 ,  3 ,  1 ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  gl - > addLayout ( build_stat ( metric  ?  " KM "  :  " MILES " ,  week_distance ) ,  7 ,  1 ,  3 ,  1 ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  gl - > addLayout ( build_stat ( " HOURS " ,  week [ " minutes " ] . toDouble ( )  /  60 ) ,  7 ,  2 ,  3 ,  1 ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  setLayout ( gl ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  setStyleSheet ( R " ( 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								    QLabel  { 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								      font - size :  48 px ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      font - weight :  600 ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  ) " ); 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								} 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								DriveStats : : DriveStats ( QWidget  * parent )  :  QWidget ( parent )  { 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  QString  dongle_id  =  QString : : fromStdString ( Params ( ) . get ( " DongleId " ) ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  QString  token  =  create_jwt ( dongle_id ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  QNetworkAccessManager  * manager  =  new  QNetworkAccessManager ( this ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  connect ( manager ,  & QNetworkAccessManager : : finished ,  this ,  & DriveStats : : replyFinished ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  QNetworkRequest  request ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  request . setUrl ( QUrl ( " https://api.commadotai.com/v1.1/devices/ "  +  dongle_id  +  " /stats " ) ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  request . setRawHeader ( " Authorization " ,  ( " JWT  " + token ) . toUtf8 ( ) ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  manager - > get ( request ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}