Qt setup + installer (#2511)
	
		
	
				
					
				
			* getting started * setup screens * cleanupg * url input * installer * setup * installerpull/214/head
							parent
							
								
									91f79acac3
								
							
						
					
					
						commit
						7b72bbe9f3
					
				
				 5 changed files with 283 additions and 0 deletions
			
			
		| @ -0,0 +1,68 @@ | |||||||
|  | #include <time.h> | ||||||
|  | #include <unistd.h> | ||||||
|  | #include <cstdlib> | ||||||
|  | #include <iostream> | ||||||
|  | 
 | ||||||
|  | #ifndef BRANCH | ||||||
|  | #define BRANCH "master" | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|  | #define GIT_CLONE_COMMAND "git clone https://github.com/commaai/openpilot.git"
 | ||||||
|  | 
 | ||||||
|  | #define CONTINUE_PATH "/home/comma/continue.sh" | ||||||
|  | 
 | ||||||
|  | bool time_valid() { | ||||||
|  |   time_t rawtime; | ||||||
|  |   time(&rawtime); | ||||||
|  | 
 | ||||||
|  |   struct tm * sys_time = gmtime(&rawtime); | ||||||
|  |   return (1900 + sys_time->tm_year) >= 2019; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | int fresh_clone() { | ||||||
|  |   int err; | ||||||
|  | 
 | ||||||
|  |   // Cleanup
 | ||||||
|  |   err = std::system("rm -rf /tmp/openpilot"); | ||||||
|  |   if(err) return 1; | ||||||
|  |   err = std::system("rm -rf /data/openpilot"); | ||||||
|  |   if(err) return 1; | ||||||
|  | 
 | ||||||
|  |   // Clone
 | ||||||
|  |   err = std::system(GIT_CLONE_COMMAND " -b " BRANCH " --depth=1 /tmp/openpilot"); | ||||||
|  |   if(err) return 1; | ||||||
|  |   err = std::system("cd /tmp/openpilot && git submodule update --init"); | ||||||
|  |   if(err) return 1; | ||||||
|  | 
 | ||||||
|  |   err = std::system("mv /tmp/openpilot /data"); | ||||||
|  |   if(err) return 1; | ||||||
|  | 
 | ||||||
|  |   return 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | int install() { 
 | ||||||
|  |   int err; | ||||||
|  | 
 | ||||||
|  |   // TODO: Disable SSH after install done
 | ||||||
|  | 
 | ||||||
|  |   // Wait for valid time
 | ||||||
|  |   while (!time_valid()) { | ||||||
|  |     usleep(500 * 1000); | ||||||
|  |     std::cout << "Waiting for valid time\n"; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   std::cout << "Doing fresh clone\n"; | ||||||
|  |   err = fresh_clone(); | ||||||
|  |   if(err) return 1; | ||||||
|  | 
 | ||||||
|  |   // Write continue.sh
 | ||||||
|  |   err = std::system("cp /data/openpilot/installer/continue_openpilot.sh " CONTINUE_PATH); | ||||||
|  |   if(err == -1) return 1; | ||||||
|  | 
 | ||||||
|  |   return 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | int main(int argc, char *argv[]) { | ||||||
|  |   // TODO: make a small installation UI
 | ||||||
|  |   return install(); | ||||||
|  | } | ||||||
| @ -0,0 +1,184 @@ | |||||||
|  | #include <stdio.h> | ||||||
|  | #include <curl/curl.h> | ||||||
|  | 
 | ||||||
|  | #include <QString> | ||||||
|  | #include <QLabel> | ||||||
|  | #include <QWidget> | ||||||
|  | #include <QLineEdit> | ||||||
|  | #include <QPushButton> | ||||||
|  | #include <QVBoxLayout> | ||||||
|  | #include <QApplication> | ||||||
|  | 
 | ||||||
|  | #include "setup.hpp" | ||||||
|  | 
 | ||||||
|  | #ifdef QCOM2 | ||||||
|  | #include <qpa/qplatformnativeinterface.h> | ||||||
|  | #include <QPlatformSurfaceEvent> | ||||||
|  | #include <wayland-client-protocol.h> | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | int download(std::string url) { | ||||||
|  |   CURL *curl; | ||||||
|  |   curl = curl_easy_init(); | ||||||
|  |   if (!curl) return -1; | ||||||
|  | 
 | ||||||
|  |   FILE *fp; | ||||||
|  |   fp = fopen("/tmp/installer", "wb"); | ||||||
|  |   curl_easy_setopt(curl, CURLOPT_URL, url.c_str()); | ||||||
|  |   curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, NULL); | ||||||
|  |   curl_easy_setopt(curl, CURLOPT_WRITEDATA, fp); | ||||||
|  |   curl_easy_setopt (curl, CURLOPT_VERBOSE, 1L); | ||||||
|  |   curl_easy_perform(curl); | ||||||
|  |   curl_easy_cleanup(curl); | ||||||
|  |   fclose(fp); | ||||||
|  |   return 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | QLabel * title_label(QString text) { | ||||||
|  |   QLabel *l = new QLabel(text); | ||||||
|  |   l->setStyleSheet(R"( | ||||||
|  |     QLabel { | ||||||
|  |       font-size: 100px; | ||||||
|  |       font-weight: bold; | ||||||
|  |     } | ||||||
|  |   )"); | ||||||
|  |   return l; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | QWidget * Setup::getting_started() { | ||||||
|  |   QVBoxLayout *main_layout = new QVBoxLayout(); | ||||||
|  |   main_layout->setContentsMargins(200, 100, 200, 100); | ||||||
|  | 
 | ||||||
|  |   main_layout->addWidget(title_label("Getting Started"), 0, Qt::AlignCenter); | ||||||
|  | 
 | ||||||
|  |   QLabel *body = new QLabel("Before we get on the road, let's finish\ninstallation and cover some details."); | ||||||
|  |   body->setStyleSheet(R"(font-size: 65px;)"); | ||||||
|  |   main_layout->addWidget(body, 0, Qt::AlignCenter); | ||||||
|  | 
 | ||||||
|  |   main_layout->addSpacing(100); | ||||||
|  | 
 | ||||||
|  |   QPushButton *btn = new QPushButton("Continue"); | ||||||
|  |   main_layout->addWidget(btn); | ||||||
|  |   QObject::connect(btn, SIGNAL(released()), this, SLOT(nextPage())); | ||||||
|  | 
 | ||||||
|  |   main_layout->addSpacing(100); | ||||||
|  | 
 | ||||||
|  |   QWidget *widget = new QWidget(); | ||||||
|  |   widget->setLayout(main_layout); | ||||||
|  |   return widget; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | QWidget * Setup::network_setup() { | ||||||
|  |   QVBoxLayout *main_layout = new QVBoxLayout(); | ||||||
|  |   main_layout->setMargin(100); | ||||||
|  | 
 | ||||||
|  |   main_layout->addWidget(title_label("Connect to WiFi"), 0, Qt::AlignCenter); | ||||||
|  | 
 | ||||||
|  |   QPushButton *btn = new QPushButton("Continue"); | ||||||
|  |   main_layout->addWidget(btn); | ||||||
|  |   QObject::connect(btn, SIGNAL(released()), this, SLOT(nextPage())); | ||||||
|  | 
 | ||||||
|  |   QWidget *widget = new QWidget(); | ||||||
|  |   widget->setLayout(main_layout); | ||||||
|  |   return widget; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | QWidget * Setup::software_selection() { | ||||||
|  |   QVBoxLayout *main_layout = new QVBoxLayout(); | ||||||
|  |   main_layout->setMargin(100); | ||||||
|  | 
 | ||||||
|  |   main_layout->addWidget(title_label("Choose Software"), 0, Qt::AlignCenter); | ||||||
|  | 
 | ||||||
|  |   QPushButton *dashcam_btn = new QPushButton("Dashcam"); | ||||||
|  |   main_layout->addWidget(dashcam_btn); | ||||||
|  |   QObject::connect(dashcam_btn, SIGNAL(released()), this, SLOT(nextPage())); | ||||||
|  | 
 | ||||||
|  |   main_layout->addSpacing(50); | ||||||
|  | 
 | ||||||
|  |   const char* env_url = getenv("CUSTOM_URL"); | ||||||
|  |   QString default_url = env_url == NULL ? "" : QString::fromStdString(env_url); | ||||||
|  |   url_input = new QLineEdit(default_url); | ||||||
|  |   url_input->setStyleSheet(R"( | ||||||
|  |     color: black; | ||||||
|  |     background-color: white; | ||||||
|  |     font-size: 55px; | ||||||
|  |     padding: 40px; | ||||||
|  |   )"); | ||||||
|  |   main_layout->addWidget(url_input); | ||||||
|  | 
 | ||||||
|  |   QPushButton *custom_btn = new QPushButton("Custom"); | ||||||
|  |   main_layout->addWidget(custom_btn); | ||||||
|  |   QObject::connect(custom_btn, SIGNAL(released()), this, SLOT(nextPage())); | ||||||
|  | 
 | ||||||
|  |   QWidget *widget = new QWidget(); | ||||||
|  |   widget->setLayout(main_layout); | ||||||
|  |   return widget; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | QWidget * Setup::downloading() { | ||||||
|  |   QVBoxLayout *main_layout = new QVBoxLayout(); | ||||||
|  | 
 | ||||||
|  |   main_layout->addWidget(title_label("Downloading..."), 0, Qt::AlignCenter); | ||||||
|  | 
 | ||||||
|  |   QWidget *widget = new QWidget(); | ||||||
|  |   widget->setLayout(main_layout); | ||||||
|  |   return widget; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void Setup::nextPage() { | ||||||
|  |   layout->setCurrentIndex(layout->currentIndex() + 1); | ||||||
|  | 
 | ||||||
|  |   // start download
 | ||||||
|  |   if (layout->currentIndex() == layout->count() - 1)  { | ||||||
|  |     std::string url = url_input->text().toStdString(); | ||||||
|  |     download(url); | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | Setup::Setup(QWidget *parent) { | ||||||
|  |   layout = new QStackedLayout(); | ||||||
|  |   layout->addWidget(getting_started()); | ||||||
|  |   layout->addWidget(network_setup()); | ||||||
|  |   layout->addWidget(software_selection()); | ||||||
|  |   layout->addWidget(downloading()); | ||||||
|  | 
 | ||||||
|  |   setLayout(layout); | ||||||
|  |   setStyleSheet(R"( | ||||||
|  |     QWidget { | ||||||
|  |       color: white; | ||||||
|  |       background-color: black; | ||||||
|  |     } | ||||||
|  |     QPushButton { | ||||||
|  |       font-size: 60px; | ||||||
|  |       padding: 60px; | ||||||
|  |       width: 800px; | ||||||
|  |       color: white; | ||||||
|  |       background-color: blue; | ||||||
|  |     } | ||||||
|  |   )"); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | int main(int argc, char *argv[]) { | ||||||
|  | #ifdef QCOM2 | ||||||
|  |   int w = 2160, h = 1080; | ||||||
|  | #else | ||||||
|  |   int w = 1920, h = 1080; | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|  |   QApplication a(argc, argv); | ||||||
|  | 
 | ||||||
|  |   Setup setup; | ||||||
|  |   setup.setFixedSize(w, h); | ||||||
|  |   setup.show(); | ||||||
|  | 
 | ||||||
|  | #ifdef QCOM2 | ||||||
|  |   QPlatformNativeInterface *native = QGuiApplication::platformNativeInterface(); | ||||||
|  |   wl_surface *s = reinterpret_cast<wl_surface*>(native->nativeResourceForWindow("surface", setup.windowHandle())); | ||||||
|  |   wl_surface_set_buffer_transform(s, WL_OUTPUT_TRANSFORM_270); | ||||||
|  |   wl_surface_commit(s); | ||||||
|  |   setup.showFullScreen(); | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|  |   return a.exec(); | ||||||
|  | } | ||||||
| @ -0,0 +1,23 @@ | |||||||
|  | #include <QWidget> | ||||||
|  | #include <QLineEdit> | ||||||
|  | #include <QStackedLayout> | ||||||
|  | 
 | ||||||
|  | class Setup : public QWidget { | ||||||
|  |   Q_OBJECT | ||||||
|  | 
 | ||||||
|  | public: | ||||||
|  |   explicit Setup(QWidget *parent = 0); | ||||||
|  | 
 | ||||||
|  | private: | ||||||
|  |   QStackedLayout *layout; | ||||||
|  | 
 | ||||||
|  |   QLineEdit *url_input; | ||||||
|  | 
 | ||||||
|  |   QWidget *getting_started(); | ||||||
|  |   QWidget *network_setup(); | ||||||
|  |   QWidget *software_selection(); | ||||||
|  |   QWidget *downloading(); | ||||||
|  | 
 | ||||||
|  | public slots: | ||||||
|  |   void nextPage(); | ||||||
|  | }; | ||||||
					Loading…
					
					
				
		Reference in new issue