├── .gitignore ├── ESP-codes ├── Main-code │ ├── Main-code.ino │ ├── data │ │ ├── check-email.html │ │ ├── check.png │ │ ├── email-check.png │ │ ├── icons8_GPS_Signal_128px.png │ │ ├── index.html │ │ ├── login.html │ │ ├── map-1272165_1280.png │ │ ├── register-done.html │ │ ├── script.js │ │ ├── signin.html │ │ ├── src │ │ │ ├── bootstrap.bundle.min.js │ │ │ ├── bootstrap.min.css │ │ │ └── jquery-3.6.4.min.js │ │ └── style.css │ └── email.h ├── Signup-firebase-code │ └── Signup-firebase-code.ino ├── Test_Neo7m_TTGO │ └── Test_Neo7m_TTGO.ino └── Test_SIM800L_TTGO_HTTP_request │ └── Test_SIM800L_TTGO_HTTP_request.ino ├── LICENSE.md ├── README.md ├── backend ├── .dockerignore ├── .gitignore ├── Dockerfile ├── HiveMQ.js ├── package-lock.json ├── package.json └── server.js ├── conceptionPCB ├── PCB_PCB_gps-tracker_2023-06-04.json ├── PCB_PCB_gps-tracker_2023-06-04.pdf └── SCH_gps-tracker_2023-06-04.json ├── docker-compose.yml ├── frontend ├── .gitignore ├── Dockerfile ├── README.md ├── babel.config.js ├── jsconfig.json ├── package-lock.json ├── package.json ├── public │ ├── css │ │ └── style.css │ ├── favicon.ico │ ├── index.html │ └── js │ │ └── main.js ├── src │ ├── App.vue │ ├── assets │ │ ├── 1.png │ │ ├── 3.jpg │ │ ├── 3.png │ │ ├── GPS.png │ │ ├── cc.jpg │ │ ├── cone.jpg │ │ ├── flotte.png │ │ ├── image.png │ │ ├── img.png │ │ ├── img │ │ │ ├── 3.png │ │ │ ├── apple-touch-icon.png │ │ │ ├── clients │ │ │ │ ├── client-1.png │ │ │ │ ├── client-2.png │ │ │ │ ├── client-3.png │ │ │ │ ├── client-5.png │ │ │ │ ├── client-6.png │ │ │ │ └── client-7.png │ │ │ ├── cta-bg.jpg │ │ │ ├── favicon.png │ │ │ ├── gps.jpg │ │ │ ├── hero-img.png │ │ │ ├── portfolio │ │ │ │ ├── portfolio-1.jpg │ │ │ │ ├── portfolio-2.jpg │ │ │ │ ├── portfolio-3.jpg │ │ │ │ ├── portfolio-4.jpg │ │ │ │ ├── portfolio-5.jpg │ │ │ │ ├── portfolio-6.jpg │ │ │ │ ├── portfolio-7.jpg │ │ │ │ ├── portfolio-8.jpg │ │ │ │ ├── portfolio-9.jpg │ │ │ │ ├── portfolio-details-1.jpg │ │ │ │ ├── portfolio-details-2.jpg │ │ │ │ └── portfolio-details-3.jpg │ │ │ ├── skills.png │ │ │ ├── team │ │ │ │ ├── team-1.jpg │ │ │ │ ├── team-2.jpg │ │ │ │ ├── team-3.jpg │ │ │ │ └── team-4.jpg │ │ │ └── why-us.png │ │ ├── imge.png │ │ ├── location.png │ │ ├── logo.png │ │ ├── med.jpg │ │ ├── media.jpg │ │ ├── message.png │ │ ├── ouma.png │ │ ├── phone.jpg │ │ ├── position.png │ │ ├── trac.jpg │ │ └── traceur.png │ ├── components │ │ ├── AboutView.vue │ │ ├── Component3.vue │ │ ├── ContactView.vue │ │ ├── HomeView.vue │ │ ├── LoginView.vue │ │ ├── NavbarView.vue │ │ ├── PricingView.vue │ │ ├── ServicesView.vue │ │ ├── SideBarView.vue │ │ ├── UserView.vue │ │ └── layout │ │ │ ├── user-history.vue │ │ │ └── user-homeView.vue │ ├── firebase.js │ ├── main.js │ └── routes.js └── vue.config.js └── pictures ├── configuration.png ├── configuration1.png ├── home-interface.png ├── login-interface.png ├── services-interface.png ├── synoptique.png ├── user-history.png └── user-interface.png /.gitignore: -------------------------------------------------------------------------------- 1 | data 2 | documentation -------------------------------------------------------------------------------- /ESP-codes/Main-code/Main-code.ino: -------------------------------------------------------------------------------- 1 | /* 2 | Author: Rani zouaoui + Oumaima Slema 3 | I wrote this code as part of my PFE which is called "Car Tracker". 4 | The code provides a server that provides an interactive configuration interface for the entire project. 5 | If our product is correctly configured, a green LED will light up and 6 | The authentication information (User name, password, E-mail, Access code) will be sent to the e-mail offered by the user. 7 | Our code also offers two types of connectivity (Wi-Fi & GPRS) 8 | */ 9 | 10 | //? This section includes the necessary libraries for code execution 11 | 12 | #include // Library for WiFi connectivity 13 | #include // Arduino core library 14 | #include // Library for asynchronous web server functionality 15 | #include // Asynchronous TCP library 16 | #include "SPIFFS.h" // SPIFFS (SPI Flash File System) library for file operations 17 | #include // ESP32 system library 18 | #include // ESP32 watchdog timer library 19 | #include "esp_err.h" // ESP32 error handling library 20 | #include "email.h" // Library for sending email 21 | #include // String manipulation library 22 | #include "esp_err.h" // ESP32 error handling library 23 | #include "driver/adc.h" // ADC (Analog-to-Digital Converter) library 24 | #include // MQTT library for ESP32 25 | #include // Secure WiFi client library 26 | #include // Library for parsing NMEA GPS data 27 | #include // Library for software serial communication 28 | #include // Firebase library for ESP32 29 | #include // Token helper library for Firebase authentication 30 | #include // Real-Time Database helper library for Firebase 31 | #define API_KEY "put your API key for Firebase" // API key for Firebase 32 | #define DATABASE_URL "put your URL of the Firebase Real-Time Database" // URL of the Firebase Real-Time Database 33 | 34 | SoftwareSerial gpsSerial(16, 17); // RX, TX pins for software serial on ESP 32 V1 35 | TinyGPSPlus gps; 36 | WiFiClientSecure espClient; // for no secure connection use WiFiClient instead of WiFiClientSecure 37 | PubSubClient client(espClient); 38 | 39 | //---- MQTT Broker settings 40 | const char *mqtt_server = "put your MQTT broker server address"; // MQTT broker server address 41 | const char *mqtt_username = "put your MQTT broker username"; // MQTT broker username 42 | const char *mqtt_password = "put your MQTT broker password"; // MQTT broker password 43 | const int mqtt_port = 8883; // MQTT broker port number 44 | 45 | float latitude = 37.2669776; 46 | float longitude = 9.8776592; 47 | float gpsspeed = 0; 48 | int start = 0; // variable that will be used to block mqtt client initialization if the internet connection is not established 49 | 50 | const int pin = 2; // Reset button 51 | 52 | // Mqtt topics 53 | const char *sensor1_topic = "latitude"; 54 | const char *sensor2_topic = "longitude"; 55 | const char *sensor3_topic = "speed"; 56 | const char *command2_topic = "startgps"; 57 | static const char *root_ca PROGMEM = R"EOF( 58 | -----BEGIN CERTIFICATE----- 59 | MIIFazCCA1OgAwIBAgIRAIIQz7DSQONZRGPgu2OCiwAwDQYJKoZIhvcNAQELBQAw 60 | TzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2Vh 61 | cmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwHhcNMTUwNjA0MTEwNDM4 62 | WhcNMzUwNjA0MTEwNDM4WjBPMQswCQYDVQQGEwJVUzEpMCcGA1UEChMgSW50ZXJu 63 | ZXQgU2VjdXJpdHkgUmVzZWFyY2ggR3JvdXAxFTATBgNVBAMTDElTUkcgUm9vdCBY 64 | MTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAK3oJHP0FDfzm54rVygc 65 | h77ct984kIxuPOZXoHj3dcKi/vVqbvYATyjb3miGbESTtrFj/RQSa78f0uoxmyF+ 66 | 0TM8ukj13Xnfs7j/EvEhmkvBioZxaUpmZmyPfjxwv60pIgbz5MDmgK7iS4+3mX6U 67 | A5/TR5d8mUgjU+g4rk8Kb4Mu0UlXjIB0ttov0DiNewNwIRt18jA8+o+u3dpjq+sW 68 | T8KOEUt+zwvo/7V3LvSye0rgTBIlDHCNAymg4VMk7BPZ7hm/ELNKjD+Jo2FR3qyH 69 | B5T0Y3HsLuJvW5iB4YlcNHlsdu87kGJ55tukmi8mxdAQ4Q7e2RCOFvu396j3x+UC 70 | B5iPNgiV5+I3lg02dZ77DnKxHZu8A/lJBdiB3QW0KtZB6awBdpUKD9jf1b0SHzUv 71 | KBds0pjBqAlkd25HN7rOrFleaJ1/ctaJxQZBKT5ZPt0m9STJEadao0xAH0ahmbWn 72 | OlFuhjuefXKnEgV4We0+UXgVCwOPjdAvBbI+e0ocS3MFEvzG6uBQE3xDk3SzynTn 73 | jh8BCNAw1FtxNrQHusEwMFxIt4I7mKZ9YIqioymCzLq9gwQbooMDQaHWBfEbwrbw 74 | qHyGO0aoSCqI3Haadr8faqU9GY/rOPNk3sgrDQoo//fb4hVC1CLQJ13hef4Y53CI 75 | rU7m2Ys6xt0nUW7/vGT1M0NPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNV 76 | HRMBAf8EBTADAQH/MB0GA1UdDgQWBBR5tFnme7bl5AFzgAiIyBpY9umbbjANBgkq 77 | hkiG9w0BAQsFAAOCAgEAVR9YqbyyqFDQDLHYGmkgJykIrGF1XIpu+ILlaS/V9lZL 78 | ubhzEFnTIZd+50xx+7LSYK05qAvqFyFWhfFQDlnrzuBZ6brJFe+GnY+EgPbk6ZGQ 79 | 3BebYhtF8GaV0nxvwuo77x/Py9auJ/GpsMiu/X1+mvoiBOv/2X/qkSsisRcOj/KK 80 | NFtY2PwByVS5uCbMiogziUwthDyC3+6WVwW6LLv3xLfHTjuCvjHIInNzktHCgKQ5 81 | ORAzI4JMPJ+GslWYHb4phowim57iaztXOoJwTdwJx4nLCgdNbOhdjsnvzqvHu7Ur 82 | TkXWStAmzOVyyghqpZXjFaH3pO3JLF+l+/+sKAIuvtd7u+Nxe5AW0wdeRlN8NwdC 83 | jNPElpzVmbUq4JUagEiuTDkHzsxHpFKVK7q4+63SM1N95R1NbdWhscdCb+ZAJzVc 84 | oyi3B43njTOQ5yOf+1CceWxG1bQVs5ZufpsMljq4Ui0/1lvh+wjChP4kqKOJ2qxq 85 | 4RgqsahDYVvTH9w7jXbyLeiNdd8XM2w9U/t7y0Ff/9yi0GE44Za4rF2LN9d11TPA 86 | mRGunUHBcnWEvgJBQl9nJEiU0Zsnvgc/ubhPgXRR4Xq37Z0j4r7g1SgEEzwxA57d 87 | emyPxgcYxn/eR44/KJ4EBs+lVDR3veyJm+kXQ99b21/+jh5Xos1AnX5iItreGCc= 88 | -----END CERTIFICATE----- 89 | )EOF"; 90 | 91 | /* E-mail credentials */ 92 | #define SMTP_HOST "smtp.gmail.com" 93 | #define SMTP_PORT 465 94 | #define AUTHOR_EMAIL "gps.tracker.sender@gmail.com" 95 | #define AUTHOR_PASSWORD "zlmmjpmezglzxygc" // This code is generated from google 96 | 97 | // Create AsyncWebServer object on port 80 98 | AsyncWebServer server(80); 99 | 100 | // Search for parameter in HTTP requests 101 | const char *PARAM_INPUT_1 = "Username"; 102 | const char *PARAM_INPUT_2 = "password"; 103 | const char *PARAM_INPUT_3 = "email"; 104 | const char *PARAM_INPUT_4 = "inlineRadioOptions"; 105 | const char *PARAM_INPUT_5 = "wifi-ssid"; 106 | const char *PARAM_INPUT_6 = "wifi-password"; 107 | 108 | // Sccess point settings 109 | const char *soft_ap_ssid = "GPS-Tracker"; 110 | const char *soft_ap_password = NULL; 111 | 112 | // Variables 113 | String username; 114 | String password; 115 | String email; 116 | String code; 117 | String wifissid; 118 | String wifipassword; 119 | String connectionoption; 120 | String inputusername; 121 | String inputpassword; 122 | String checkemail; 123 | char incomingChar; 124 | int Value; 125 | // File paths to save input values permanently 126 | const char *usernamePath = "/username.txt"; 127 | const char *passwordPath = "/password.txt"; 128 | const char *emailPath = "/email.txt"; 129 | const char *codePath = "/code.txt"; 130 | const char *ssidPath = "/ssid.txt"; 131 | const char *wifipasswordPath = "/wifipassword.txt"; 132 | const char *checkemailPath = "/check.txt"; 133 | // Method to initialize SPIFFS 134 | void initSPIFFS() 135 | { 136 | if (!SPIFFS.begin(true)) 137 | { 138 | Serial.println("An error has occurred while mounting SPIFFS"); 139 | } 140 | Serial.println("SPIFFS mounted successfully"); 141 | } 142 | 143 | void senddata_To_Firebase(String acces_code, String email, String password, String username) 144 | { 145 | unsigned long dataMillis = 0; 146 | int count = 0; 147 | bool signupOK = false; 148 | /* 4. Define the Firebase Data object */ 149 | FirebaseData fbdo; 150 | /* 5. Define the FirebaseAuth data for authentication data */ 151 | FirebaseAuth auth; 152 | 153 | /* 6. Define the FirebaseConfig data for config data */ 154 | FirebaseConfig config; 155 | Serial.printf("Firebase Client v%s\n\n", FIREBASE_CLIENT_VERSION); 156 | /* Assign the API key (required) */ 157 | config.api_key = API_KEY; 158 | /* Assign the RTDB URL */ 159 | config.database_url = DATABASE_URL; 160 | Firebase.reconnectWiFi(true); 161 | Serial.print("Sign up new user... "); 162 | /* Sign up */ 163 | if (Firebase.signUp(&config, &auth, email, password)) 164 | { 165 | Serial.println("ok"); 166 | signupOK = true; 167 | } 168 | else 169 | { 170 | Serial.printf("%s\n", config.signer.signupError.message.c_str()); 171 | } 172 | config.token_status_callback = tokenStatusCallback; // see addons/TokenHelper.h 173 | Firebase.begin(&config, &auth); 174 | String name = auth.token.uid.c_str(); //<- user uid 175 | if (millis() - dataMillis > 5000 && signupOK && Firebase.ready()) 176 | { 177 | dataMillis = millis(); 178 | // Create a JSON object with the data 179 | FirebaseJson json; 180 | json.add("uid", name); 181 | json.add("username", username); 182 | json.add("acces_code", acces_code); 183 | // Insert the data into the "usersdata" collection 184 | if (Firebase.pushJSON(fbdo, "/usersdata", json)) 185 | { 186 | Serial.println("Data inserted successfully"); 187 | } 188 | else 189 | { 190 | Serial.println("Data insert failed"); 191 | } 192 | } 193 | } 194 | // MQtt Client function 195 | void reconnect() 196 | { 197 | // Loop until we're reconnected 198 | while (!client.connected()) 199 | { 200 | Serial.print("Attempting MQTT connection..."); 201 | String clientId = "ESP8266Client-"; // Create a random client ID 202 | clientId += String(random(0xffff), HEX); 203 | // Attempt to connect 204 | if (client.connect(clientId.c_str(), mqtt_username, mqtt_password)) 205 | { 206 | Serial.println("connected"); 207 | 208 | client.subscribe(command2_topic); // subscribe the topics here 209 | } 210 | else 211 | { 212 | Serial.print("failed, rc="); 213 | Serial.print(client.state()); 214 | Serial.println(" try again in 5 seconds"); // Wait 5 seconds before retrying 215 | delay(5000); 216 | } 217 | } 218 | } 219 | // MQtt Client function 220 | void callback(char *topic, byte *payload, unsigned int length) 221 | { 222 | String incommingMessage = ""; 223 | for (int i = 0; i < length; i++) 224 | incommingMessage += (char)payload[i]; 225 | 226 | Serial.println("Message arrived [" + String(topic) + "]" + incommingMessage); 227 | 228 | //--- check the incomming message 229 | 230 | // check for other commands 231 | // if( strcmp(topic,command2_topic) == 0){ 232 | // 233 | // } 234 | // if (incommingMessage.equals("0")) { 235 | // digitalWrite(pompe, LOW); 236 | // } 237 | // } 238 | } 239 | void publishMessage(const char *topic, String payload, boolean retained) 240 | { 241 | if (client.publish(topic, payload.c_str(), true)) 242 | Serial.println("Message publised [" + String(topic) + "]: " + payload); 243 | } 244 | 245 | // Method to read File from SPIFFS 246 | String readFile(fs::FS &fs, const char *path) 247 | { 248 | Serial.printf("Reading file: %s\r\n", path); 249 | File file = fs.open(path, "r"); 250 | String fileContent = "empty"; 251 | if (file.size() > 0) 252 | { 253 | while (file.available()) 254 | { 255 | fileContent = file.readStringUntil('\n'); 256 | break; 257 | } 258 | } 259 | file.close(); 260 | return fileContent; 261 | } 262 | 263 | // Method to write file to SPIFFS 264 | void writeFile(fs::FS &fs, const char *path, const char *message) 265 | { 266 | Serial.printf("Writing file: %s\r\n", path); 267 | 268 | File file = fs.open(path, FILE_WRITE); 269 | if (!file) 270 | { 271 | Serial.println("- failed to open file for writing"); 272 | return; 273 | } 274 | if (file.print(message)) 275 | { 276 | Serial.println("- file written"); 277 | file.close(); 278 | } 279 | else 280 | { 281 | Serial.println("- frite failed"); 282 | file.close(); 283 | } 284 | } 285 | 286 | // Method to delete Content from SPIFFS 287 | void DeleteContent(fs::FS &fs, const char *path) 288 | { 289 | fs.remove(path); 290 | Serial.println("File content deleted"); 291 | } 292 | void setup_ap(const char *ssid, const char *password) 293 | { 294 | Serial.println("\n[*] Creating ESP32 AP"); 295 | WiFi.softAP(ssid, password); 296 | Serial.print("[+] AP Created with IP Gateway "); 297 | Serial.println(WiFi.softAPIP()); 298 | } 299 | /* Callback function to get the Email sending status */ 300 | void smtpCallback(SMTP_Status status); 301 | // Method to initialize WiFi 302 | bool initWiFi(const char *wifi_network_ssid, const char *wifi_network_password) 303 | { 304 | WiFi.mode(WIFI_AP_STA); 305 | WiFi.begin(wifi_network_ssid, wifi_network_password); 306 | Serial.println("\n[*] Connecting to WiFi Network"); 307 | 308 | while (WiFi.status() != WL_CONNECTED) 309 | { 310 | Serial.print("."); 311 | delay(100); 312 | } 313 | 314 | Serial.print("\n[+] Connected to the WiFi network with local IP : "); 315 | Serial.println(WiFi.localIP()); 316 | start = 1; 317 | if (checkemail == "yes") 318 | { 319 | senddata_To_Firebase(code, email, password, username); 320 | SendEmail(email, username, password, code); 321 | DeleteContent(SPIFFS, checkemailPath); 322 | } 323 | } 324 | 325 | // Method to check Wi-Fi Connection 326 | bool check_wifi(const char *ssid, const char *password) 327 | { 328 | WiFi.mode(WIFI_AP_STA); 329 | WiFi.begin(ssid, password); 330 | int i = 0; 331 | bool isConnected = false; 332 | while (WiFi.status() != WL_CONNECTED && i < 10) 333 | { 334 | delay(500); 335 | Serial.print("."); 336 | esp_task_wdt_reset(); //! reset the watchdog timer to avoid its triggering 337 | i++; 338 | } 339 | if (i >= 10) 340 | { 341 | Serial.println("Failed to connect to WiFi"); 342 | isConnected = false; 343 | } 344 | else 345 | { 346 | Serial.println("WiFi connected successfully"); 347 | isConnected = true; 348 | } 349 | return isConnected; 350 | } 351 | // Method to restart the ESP32 and SPIFFS 352 | void resetESP32() 353 | { 354 | DeleteContent(SPIFFS, usernamePath); 355 | DeleteContent(SPIFFS, passwordPath); 356 | DeleteContent(SPIFFS, emailPath); 357 | DeleteContent(SPIFFS, codePath); 358 | DeleteContent(SPIFFS, wifipasswordPath); 359 | DeleteContent(SPIFFS, ssidPath); 360 | DeleteContent(SPIFFS, checkemailPath); 361 | esp_restart(); 362 | } 363 | 364 | // Method to Generate an access code 365 | String GenererCode() 366 | { 367 | String chaine = "AZ8E7R9TY1UIOPQS2DFG5HJK3LMWX4CV6BN"; 368 | String code; 369 | int index; 370 | 371 | for (int i = 0; i < 20; i++) 372 | { 373 | index = random(34); 374 | code += chaine[index]; 375 | } 376 | return code; 377 | } 378 | 379 | // Method to save data to SPIFFS after successful registration 380 | bool SaveDataWithWiFiConnection() 381 | { 382 | writeFile(SPIFFS, usernamePath, username.c_str()); 383 | esp_task_wdt_reset(); 384 | writeFile(SPIFFS, emailPath, email.c_str()); 385 | esp_task_wdt_reset(); 386 | writeFile(SPIFFS, passwordPath, password.c_str()); 387 | esp_task_wdt_reset(); 388 | writeFile(SPIFFS, ssidPath, wifissid.c_str()); 389 | esp_task_wdt_reset(); 390 | writeFile(SPIFFS, wifipasswordPath, wifipassword.c_str()); 391 | esp_task_wdt_reset(); 392 | writeFile(SPIFFS, checkemailPath, "yes"); 393 | esp_task_wdt_reset(); 394 | code = GenererCode(); 395 | esp_task_wdt_reset(); 396 | writeFile(SPIFFS, codePath, code.c_str()); 397 | } 398 | 399 | // Method to send the sign in credentials to user email 400 | void SendEmail(String RECIPIENT_EMAIL, String username, String password, String code) 401 | { 402 | esp_task_wdt_delete(NULL); 403 | // SMTPSession smtp; 404 | smtp.debug(1); 405 | smtp.callback(smtpCallback); 406 | /* Set the session config */ 407 | session.server.host_name = SMTP_HOST; 408 | session.server.port = SMTP_PORT; 409 | session.login.email = AUTHOR_EMAIL; 410 | session.login.password = AUTHOR_PASSWORD; 411 | session.login.user_domain = ""; 412 | 413 | /* Set the message headers */ 414 | message.sender.name = "GPS Tracker"; 415 | message.sender.email = AUTHOR_EMAIL; 416 | 417 | message.subject = "The sign in credentials"; 418 | message.addRecipient(username, RECIPIENT_EMAIL); 419 | /*Send HTML message*/ 420 | String htmlMsg = "

The sign in credentials:

- Username: " + username + "

- Email: " + RECIPIENT_EMAIL + "

- Password: " + password + "

- Access code: " + code + "

"; 421 | message.html.content = htmlMsg.c_str(); 422 | message.text.charSet = "us-ascii"; 423 | message.html.transfer_encoding = Content_Transfer_Encoding::enc_7bit; 424 | /* Connect to server with the session config */ 425 | if (!smtp.connect(&session)) 426 | return; 427 | /* Start sending Email and close the session */ 428 | if (!MailClient.sendMail(&smtp, &message)) 429 | { 430 | Serial.println("Error sending Email, " + smtp.errorReason()); 431 | } 432 | } 433 | void setup() 434 | { 435 | Serial.begin(9600); // Serial monitor for debugging 436 | pinMode(pin, INPUT); 437 | gpsSerial.begin(9600); 438 | initSPIFFS(); 439 | setup_ap(soft_ap_ssid, soft_ap_password); 440 | username = readFile(SPIFFS, usernamePath); 441 | password = readFile(SPIFFS, passwordPath); 442 | wifissid = readFile(SPIFFS, ssidPath); 443 | wifipassword = readFile(SPIFFS, wifipasswordPath); 444 | checkemail = readFile(SPIFFS, checkemailPath); 445 | email = readFile(SPIFFS, emailPath); 446 | code = readFile(SPIFFS, codePath); 447 | Serial.println(username); 448 | Serial.println(password); 449 | Serial.println(wifissid); 450 | Serial.println(wifipassword); 451 | Serial.println(code); 452 | Serial.println(email); 453 | Serial.println(checkemail); 454 | 455 | if (wifissid != "empty" && wifipassword != "empty") 456 | { 457 | initWiFi(wifissid.c_str(), wifipassword.c_str()); //? The WiFi connection will be initialized if the user has properly configured 458 | espClient.setCACert(root_ca); // enable this line and the the "certificate" code for secure connection. 459 | client.setServer(mqtt_server, mqtt_port); 460 | client.setCallback(callback); 461 | } 462 | if (username == "empty" && password == "empty") //! The configuration has not yet been carried out 463 | { 464 | // Route for root / web page 465 | server.on("/", HTTP_GET, [](AsyncWebServerRequest *request) 466 | { request->send(SPIFFS, "/signin.html", "text/html"); }); 467 | server.serveStatic("/", SPIFFS, "/"); 468 | server.on("/", HTTP_POST, [](AsyncWebServerRequest *request) 469 | { 470 | int params = request->params(); 471 | for (int i = 0; i < params; i++) { 472 | AsyncWebParameter* p = request->getParam(i); 473 | if (p->isPost()) { 474 | // HTTP POST username value 475 | if (p->name() == PARAM_INPUT_1) { 476 | username = p->value().c_str(); 477 | } 478 | // HTTP POST email value 479 | if (p->name() == PARAM_INPUT_3) { 480 | email = p->value().c_str(); 481 | } 482 | // HTTP POST password value 483 | if (p->name() == PARAM_INPUT_2) { 484 | password = p->value().c_str(); 485 | } 486 | // HTTP POST connection option(Wi-Fi or GPRS) value 487 | if (p->name() == PARAM_INPUT_4) { 488 | connectionoption = p->value().c_str(); 489 | } 490 | // HTTP POST WiFi-SSID value 491 | if (p->name() == PARAM_INPUT_5) { 492 | wifissid = p->value().c_str(); 493 | } 494 | // HTTP POST WiFi-password value 495 | if (p->name() == PARAM_INPUT_6) { 496 | wifipassword = p->value().c_str(); 497 | } 498 | } 499 | } 500 | if (connectionoption = "option1") 501 | { 502 | //? The user chooses a wifi connection 503 | // SaveDataWithWiFiConnection(); 504 | if(check_wifi(wifissid.c_str(), wifipassword.c_str())){ 505 | request->send(SPIFFS, "/register-done.html", "text/html"); 506 | }else{ 507 | request->send(200, "text/plain", "Please check your Wi-Fi settings"); 508 | } 509 | } 510 | else 511 | { 512 | request->send(200, "text/plain", "Gsm is not configured yet"); 513 | } }); 514 | 515 | // Route to reboot 516 | server.on("/reboot", HTTP_GET, [](AsyncWebServerRequest *request) 517 | { 518 | request->send(200, "text/plain", "you will receive an email in 15 seconds. you can always make additional configuration on the link: http://192.168.4.1/"); 519 | // request->send(SPIFFS, "/check-email.html", "text/html"); 520 | SaveDataWithWiFiConnection(); 521 | delay(1000); 522 | esp_restart(); }); 523 | server.begin(); 524 | } 525 | else 526 | { 527 | // Web Server Root URL / 528 | server.on("/", HTTP_GET, [](AsyncWebServerRequest *request) 529 | { request->send(SPIFFS, "/login.html", "text/html"); }); 530 | 531 | server.serveStatic("/", SPIFFS, "/"); 532 | 533 | server.on("/", HTTP_POST, [](AsyncWebServerRequest *request) 534 | { 535 | int params = request->params(); 536 | for (int i = 0; i < params; i++) { 537 | AsyncWebParameter* p = request->getParam(i); 538 | if (p->isPost()) { 539 | // HTTP POST username value 540 | if (p->name() == PARAM_INPUT_1) { 541 | inputusername = p->value().c_str(); 542 | } 543 | // HTTP POST password value 544 | if (p->name() == PARAM_INPUT_2) { 545 | inputpassword = p->value().c_str(); 546 | } 547 | } 548 | } 549 | delay(2000); 550 | if (username == inputusername && password == inputpassword) { 551 | request->send(SPIFFS, "/index.html", "text/html"); 552 | } else { 553 | request->send(200, "text/plain", "Mot de passe incorrect"); 554 | } }); 555 | server.begin(); 556 | } 557 | } 558 | 559 | void loop() 560 | { 561 | 562 | if (digitalRead(pin) == HIGH) 563 | { // Vérifie l'état de la broche 564 | resetESP32(); // Appelle la fonction resetESP32() 565 | } 566 | 567 | { 568 | if (!client.connected()) 569 | { 570 | reconnect(); 571 | } 572 | client.loop(); 573 | while (gpsSerial.available()) 574 | { 575 | if (digitalRead(pin) == HIGH) 576 | { // Vérifie l'état de la broche 577 | resetESP32(); // Appelle la fonction resetESP32() 578 | } 579 | char c = gpsSerial.read(); 580 | if (gps.encode(c)) 581 | { 582 | if (gps.location.isUpdated()) 583 | { 584 | Serial.print("Latitude: "); 585 | latitude = gps.location.lat(); 586 | Serial.println(latitude, 6); 587 | Serial.print("Longitude: "); 588 | longitude = gps.location.lng(); 589 | Serial.println(longitude, 6); 590 | publishMessage(sensor1_topic, String(latitude), true); 591 | publishMessage(sensor2_topic, String(longitude), true); 592 | } 593 | if (gps.speed.isUpdated()) 594 | { 595 | Serial.print("Speed: "); 596 | gpsspeed = gps.speed.kmph(); 597 | Serial.println(gpsspeed); 598 | publishMessage(sensor3_topic, String(gpsspeed), true); 599 | } 600 | delay(1000); 601 | } 602 | else 603 | { 604 | publishMessage(sensor1_topic, String(latitude), true); 605 | publishMessage(sensor2_topic, String(longitude), true); 606 | publishMessage(sensor3_topic, String(gpsspeed), true); 607 | delay(1000); 608 | } 609 | } 610 | } 611 | } 612 | /* Callback function to get the Email sending status */ 613 | void smtpCallback(SMTP_Status status) 614 | { 615 | /* Print the current status */ 616 | Serial.println(status.info()); 617 | 618 | /* Print the sending result */ 619 | if (status.success()) 620 | { 621 | Serial.println("----------------"); 622 | ESP_MAIL_PRINTF("Message sent success: %d\n", status.completedCount()); 623 | ESP_MAIL_PRINTF("Message sent failled: %d\n", status.failedCount()); 624 | Serial.println("----------------\n"); 625 | struct tm dt; 626 | 627 | for (size_t i = 0; i < smtp.sendingResult.size(); i++) 628 | { 629 | /* Get the result item */ 630 | SMTP_Result result = smtp.sendingResult.getItem(i); 631 | time_t ts = (time_t)result.timestamp; 632 | localtime_r(&ts, &dt); 633 | 634 | ESP_MAIL_PRINTF("Message No: %d\n", i + 1); 635 | ESP_MAIL_PRINTF("Status: %s\n", result.completed ? "success" : "failed"); 636 | ESP_MAIL_PRINTF("Date/Time: %d/%d/%d %d:%d:%d\n", dt.tm_year + 1900, dt.tm_mon + 1, dt.tm_mday, dt.tm_hour, dt.tm_min, dt.tm_sec); 637 | ESP_MAIL_PRINTF("Recipient: %s\n", result.recipients.c_str()); 638 | ESP_MAIL_PRINTF("Subject: %s\n", result.subject.c_str()); 639 | } 640 | Serial.println("----------------\n"); 641 | } 642 | } 643 | -------------------------------------------------------------------------------- /ESP-codes/Main-code/data/check-email.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Check E-mail 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 |
19 |
20 |
21 | 23 | 24 |
25 |
26 |
27 |
28 |
29 |
Check your mailbox
30 |

you will receive an email in 15 seconds. you can always make 31 | additional configuration on the link: 32 | http://192.168.4.1/ 33 |

34 |
35 | 36 | 37 |
38 | 39 | 40 |
41 |
42 |
43 |
44 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /ESP-codes/Main-code/data/check.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ranizouaoui/ESP32-Based-IoT-Tracking-System/96c806979455f6fcaf8a6591b8451af4efc24e53/ESP-codes/Main-code/data/check.png -------------------------------------------------------------------------------- /ESP-codes/Main-code/data/email-check.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ranizouaoui/ESP32-Based-IoT-Tracking-System/96c806979455f6fcaf8a6591b8451af4efc24e53/ESP-codes/Main-code/data/email-check.png -------------------------------------------------------------------------------- /ESP-codes/Main-code/data/icons8_GPS_Signal_128px.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ranizouaoui/ESP32-Based-IoT-Tracking-System/96c806979455f6fcaf8a6591b8451af4efc24e53/ESP-codes/Main-code/data/icons8_GPS_Signal_128px.png -------------------------------------------------------------------------------- /ESP-codes/Main-code/data/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | ESP WEB SERVER 6 | 7 | 8 | 9 | 29 | 30 | 31 | 32 | 33 | 34 |
35 |
36 |
37 | 39 | 40 |
41 |
42 |

Car tracker

43 |
44 |
45 |
46 |
47 |
48 |
49 |

Update your informations :

50 |
51 |
52 |
53 | 54 | 55 |
56 |
57 | 58 | 59 |
60 |
61 | 62 |
63 | @ 64 | 66 |
67 |
68 |
69 | 70 | 71 |
72 |
73 | 74 | 75 |
76 |
77 | 78 | 79 |
80 |
81 | 82 |
83 |
84 |
85 |
86 | 87 |
88 |
89 |
90 |
91 |

Update your connectivity information :

92 | 93 |
94 | 96 | 97 |
98 | 99 |
100 | 102 | 103 |
104 |
105 | 106 |
107 |
108 |
109 | 111 |
112 |
113 | 115 |
116 |
117 |
118 |
119 | 120 |
121 |
122 | 123 |
124 |
125 | 126 |
127 |
128 | 129 |
130 |
131 | 135 |
136 | 137 |
138 |
139 |
140 |
141 | 142 |
143 | 144 | 145 | -------------------------------------------------------------------------------- /ESP-codes/Main-code/data/login.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | GPS TRACKER 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 |
17 |
18 | 20 | 21 |
22 |
23 |

Car tracker

24 |
25 | 26 |
27 | 28 |
29 |
30 |
31 | 32 |
33 |
34 |
35 |
36 | 37 |
38 | 39 |
40 |
41 |
42 |

Login

43 | 44 |
45 |
46 | 47 | 49 | 50 |
51 | 52 | 53 |
54 | 55 | 56 | 58 | 59 |
60 | 64 | 65 | 66 | 67 | 68 |
69 |
70 |
71 |
72 |
73 | 74 |
75 | 76 |
77 |
78 | 79 | 80 | 81 | -------------------------------------------------------------------------------- /ESP-codes/Main-code/data/map-1272165_1280.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ranizouaoui/ESP32-Based-IoT-Tracking-System/96c806979455f6fcaf8a6591b8451af4efc24e53/ESP-codes/Main-code/data/map-1272165_1280.png -------------------------------------------------------------------------------- /ESP-codes/Main-code/data/register-done.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | GPS TRACKER 6 | 7 | 8 | 9 | 14 | 15 | 16 | 17 | 18 | 19 | 20 |
21 | 22 |
23 |
24 | 25 |
26 |

LOGIN SUCCESS

27 |
28 | 33 | 35 |
36 | 37 |
38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /ESP-codes/Main-code/data/script.js: -------------------------------------------------------------------------------- 1 | function closeWindow() { 2 | window.close(); 3 | } -------------------------------------------------------------------------------- /ESP-codes/Main-code/data/signin.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Register 6 | 7 | 8 | 9 | 10 | 30 | 31 | 32 | 33 | 34 | 35 |
36 |
37 |
38 | 40 | 41 |
42 |
43 |

Car tracker

44 |
45 | 46 |
47 | 48 |
49 |
50 |
51 | 52 |
53 |
54 |
55 |
56 | 57 |
58 | 59 |
60 |
61 |
62 |

Register

63 | 64 |
65 |
66 | 67 | 69 | 70 |
71 |
72 | 73 | 75 |
76 | 77 |
78 | 79 | 80 | 82 | 83 |
84 |
85 | 87 | 88 |
89 | 90 |
91 | 93 | 94 |
95 |
96 |
97 | 99 |
100 |
101 | 103 |
104 |
105 |
106 |
107 | 109 |
110 |
111 | 113 |
114 |
115 | 117 |
118 |
119 | 121 |
122 |
123 | 127 | 128 | 129 |
130 |
131 |
132 |
133 |
134 | 135 |
136 | 137 |
138 |
139 | 140 | 141 | 142 | -------------------------------------------------------------------------------- /ESP-codes/Main-code/data/style.css: -------------------------------------------------------------------------------- 1 | html { 2 | font-family: Arial, Helvetica, sans-serif; 3 | display: inline-block; 4 | 5 | } 6 | 7 | .topnav { 8 | overflow: hidden; 9 | background-color: #5E5DF0; 10 | } 11 | 12 | body { 13 | margin: 0; 14 | } 15 | 16 | .content { 17 | padding: 2%; 18 | } 19 | 20 | .card-grid { 21 | max-width: 950px; 22 | margin: 0 auto; 23 | display: grid; 24 | grid-gap: 2rem; 25 | grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); 26 | } 27 | 28 | .card { 29 | background-color: white; 30 | box-shadow: 2px 2px 12px 1px rgba(140, 140, 140, .5); 31 | position: relative; 32 | display: flex; 33 | flex-direction: column; 34 | min-width: 0; 35 | word-wrap: break-word; 36 | background-clip: border-box; 37 | border: 1px solid rgba(0, 0, 0, .125); 38 | border-radius: .25rem; 39 | } 40 | 41 | .button-34 { 42 | background: #5E5DF0; 43 | border-radius: 999px; 44 | box-shadow: #5E5DF0 0 10px 20px -10px; 45 | box-sizing: border-box; 46 | color: #FFFFFF; 47 | cursor: pointer; 48 | font-family: Helvetica, "Apple Color Emoji", "Segoe UI Emoji", "Noto Color Emoji", "Segoe UI Symbol", "Android Emoji", EmojiSymbols, -apple-system, system-ui, "Segoe UI", Roboto, "Helvetica Neue", "Noto Sans", sans-serif; 49 | font-size: 16px; 50 | font-weight: 700; 51 | line-height: 24px; 52 | margin-left: 20px; 53 | opacity: 1; 54 | outline: 0 solid transparent; 55 | padding: 8px 18px; 56 | user-select: none; 57 | -webkit-user-select: none; 58 | touch-action: manipulation; 59 | width: 85%; 60 | word-break: break-word; 61 | border: 0; 62 | } 63 | 64 | .success_container { 65 | width: 500px; 66 | padding: 20px; 67 | -webkit-box-shadow: 0px 0px 25px 0px rgba(209, 209, 209, 1); 68 | -moz-box-shadow: 0px 0px 25px 0px rgba(209, 209, 209, 1); 69 | box-shadow: 0px 0px 25px 0px rgba(209, 209, 209, 1); 70 | position: absolute; 71 | top: 40%; 72 | left: 50%; 73 | transform: translate(-50%, -50%); 74 | } 75 | 76 | .ic_schauhan { 77 | width: 50px; 78 | height: 50px; 79 | line-height: 50px; 80 | background: #090; 81 | text-align: center; 82 | margin: 0px auto; 83 | border-radius: 100%; 84 | 85 | } 86 | 87 | 88 | .success_container p { 89 | text-align: center; 90 | font-weight: 600; 91 | margin: 10px; 92 | font-size: 20px; 93 | padding: 0px; 94 | color: #0C0; 95 | animation: blink 1s steps(5, start) infinite; 96 | -webkit-animation: blink 1s steps(5, start) infinite; 97 | } 98 | 99 | 100 | @keyframes blink { 101 | 0% { 102 | color: #0C0; 103 | } 104 | 105 | 100% { 106 | color: green; 107 | } 108 | } 109 | 110 | .line { 111 | width: 100%; 112 | height: 6px; 113 | background: #090; 114 | position: absolute; 115 | left: 0; 116 | bottom: 0; 117 | animation: line 2s infinite alternate; 118 | } 119 | 120 | @keyframes line { 121 | 0% { 122 | width: 0%; 123 | background: #0F0; 124 | } 125 | 126 | 100% { 127 | width: 100%; 128 | background: #030; 129 | } 130 | } 131 | 132 | 133 | @media only screen and (max-width: 767px) { 134 | .success_container { 135 | width: 100%; 136 | padding: 120px 100px; 137 | box-shadow: none; 138 | position: absolute; 139 | top: 50%; 140 | left: 50%; 141 | transform: translate(-50%, -50%); 142 | } 143 | } -------------------------------------------------------------------------------- /ESP-codes/Main-code/email.h: -------------------------------------------------------------------------------- 1 | #ifndef EMAIL_H 2 | #define EMAIL_H 3 | 4 | #include 5 | #include 6 | 7 | SMTPSession smtp; 8 | ESP_Mail_Session session; 9 | SMTP_Message message; 10 | 11 | #endif -------------------------------------------------------------------------------- /ESP-codes/Signup-firebase-code/Signup-firebase-code.ino: -------------------------------------------------------------------------------- 1 | #include 2 | #if defined(ESP32) 3 | #include 4 | #include 5 | #elif defined(ESP8266) 6 | #include 7 | #include 8 | #elif defined(ARDUINO_RASPBERRY_PI_PICO_W) 9 | #include 10 | #include 11 | #endif 12 | 13 | // Provide the token generation process info. 14 | #include 15 | 16 | // Provide the RTDB payload printing info and other helper functions. 17 | #include 18 | 19 | #define API_KEY "AIzaSyB9G1utWxdOjattwoSMlHeFq9lFg1Vc7fg" 20 | /* 3. If work with RTDB, define the RTDB URL */ 21 | #define DATABASE_URL "https://gps-tracker-fafb6-default-rtdb.europe-west1.firebasedatabase.app/" 22 | /* 4. Define the Firebase Data object */ 23 | FirebaseData fbdo; 24 | /* 5. Define the FirebaseAuth data for authentication data */ 25 | FirebaseAuth auth; 26 | 27 | /* 6. Define the FirebaseConfig data for config data */ 28 | FirebaseConfig config; 29 | 30 | /* 1. Define the WiFi credentials */ 31 | #define WIFI_SSID "Redmi" 32 | #define WIFI_PASSWORD "raniphone123" 33 | 34 | void senddata_To_Firebase(String acces_code, String email, String password ,String username ){ 35 | unsigned long dataMillis = 0; 36 | int count = 0; 37 | bool signupOK = false; 38 | Serial.printf("Firebase Client v%s\n\n", FIREBASE_CLIENT_VERSION); 39 | /* Assign the API key (required) */ 40 | config.api_key = API_KEY; 41 | /* Assign the RTDB URL */ 42 | config.database_url = DATABASE_URL; 43 | Firebase.reconnectWiFi(true); 44 | Serial.print("Sign up new user... "); 45 | /* Sign up */ 46 | if (Firebase.signUp(&config, &auth, email, password)) 47 | { 48 | Serial.println("ok"); 49 | signupOK = true; 50 | } 51 | else 52 | { 53 | Serial.printf("%s\n", config.signer.signupError.message.c_str()); 54 | } 55 | config.token_status_callback = tokenStatusCallback; // see addons/TokenHelper.h 56 | Firebase.begin(&config, &auth); 57 | String name= auth.token.uid.c_str(); //<- user uid 58 | if (millis() - dataMillis > 5000 && signupOK && Firebase.ready()) 59 | { 60 | dataMillis = millis(); 61 | // Create a JSON object with the data 62 | FirebaseJson json; 63 | json.add("uid", name); 64 | json.add("username", username); 65 | json.add("acces_code", acces_code); 66 | // Insert the data into the "usersdata" collection 67 | if (Firebase.pushJSON(fbdo, "/usersdata", json)) { 68 | Serial.println("Data inserted successfully"); 69 | } else { 70 | Serial.println("Data insert failed"); 71 | } 72 | } 73 | 74 | } 75 | String acces_code ="7IG8BGZ24PB4Z99VDU3F"; 76 | String email ="oumaima.slema@gmail.com"; 77 | String password ="fuck1234"; 78 | String username ="oumaima"; 79 | /** 2. Define the API key 80 | * 81 | * The API key can be obtained since you created the project and set up 82 | * the Authentication in Firebase console. 83 | * 84 | * You may need to enable the Identity provider at https://console.cloud.google.com/customer-identity/providers 85 | * Select your project, click at ENABLE IDENTITY PLATFORM button. 86 | * The API key also available by click at the link APPLICATION SETUP DETAILS. 87 | * 88 | */ 89 | 90 | 91 | 92 | 93 | 94 | void setup() 95 | { 96 | 97 | Serial.begin(115200); 98 | 99 | WiFi.begin(WIFI_SSID, WIFI_PASSWORD); 100 | Serial.print("Connecting to Wi-Fi"); 101 | while (WiFi.status() != WL_CONNECTED) 102 | { 103 | Serial.print("."); 104 | delay(300); 105 | } 106 | Serial.println(); 107 | Serial.print("Connected with IP: "); 108 | Serial.println(WiFi.localIP()); 109 | Serial.println(); 110 | senddata_To_Firebase(acces_code,email,password ,username ); 111 | } 112 | 113 | void loop() 114 | { 115 | } 116 | -------------------------------------------------------------------------------- /ESP-codes/Test_Neo7m_TTGO/Test_Neo7m_TTGO.ino: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | SoftwareSerial gpsSerial(4, 2); // RX, TX pins for software serial on TTGO V1 5 | TinyGPSPlus gps; // TinyGPS++ object 6 | 7 | void setup() { 8 | Serial.begin(9600); // Serial monitor for debugging 9 | gpsSerial.begin(9600); // NEO-7M baud rate 10 | 11 | delay(1000); // Wait for GPS module to initialize 12 | } 13 | 14 | void loop() { 15 | while (gpsSerial.available()) { 16 | char c = gpsSerial.read(); 17 | if (gps.encode(c)) { 18 | if (gps.location.isUpdated()) { 19 | Serial.print("Latitude: "); 20 | Serial.println(gps.location.lat(), 6); 21 | Serial.print("Longitude: "); 22 | Serial.println(gps.location.lng(), 6); 23 | } 24 | if (gps.altitude.isUpdated()) { 25 | Serial.print("Altitude: "); 26 | Serial.println(gps.altitude.meters()); 27 | } 28 | if (gps.speed.isUpdated()) { 29 | Serial.print("Speed: "); 30 | Serial.println(gps.speed.kmph()); 31 | } 32 | if (gps.course.isUpdated()) { 33 | Serial.print("Course: "); 34 | Serial.println(gps.course.deg()); 35 | } 36 | if (gps.date.isUpdated() && gps.time.isUpdated()) { 37 | Serial.print("Date/Time: "); 38 | Serial.print(gps.date.year()); 39 | Serial.print("/"); 40 | Serial.print(gps.date.month()); 41 | Serial.print("/"); 42 | Serial.print(gps.date.day()); 43 | Serial.print(" "); 44 | Serial.print(gps.time.hour()); 45 | Serial.print(":"); 46 | Serial.print(gps.time.minute()); 47 | Serial.print(":"); 48 | Serial.println(gps.time.second()); 49 | } 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /ESP-codes/Test_SIM800L_TTGO_HTTP_request/Test_SIM800L_TTGO_HTTP_request.ino: -------------------------------------------------------------------------------- 1 | // TTGO T-Call pins 2 | #define MODEM_RX 26 3 | #define MODEM_TX 27 4 | #define MODEM_PWRKEY 4 5 | #define MODEM_RST 5 6 | #define MODEM_POWER 23 7 | #define TINY_GSM_MODEM_SIM800 // Modem is SIM800 8 | #define TINY_GSM_RX_BUFFER 1024 // Set RX buffer to 1Kb 9 | #include 10 | #include 11 | #include 12 | 13 | // APN credentials 14 | const char apn[] = "internet.tn"; 15 | const char gprsUser[] = ""; 16 | const char gprsPass[] = ""; 17 | 18 | 19 | 20 | // Initialize TinyGSM client 21 | TinyGsm modem(Serial2); 22 | 23 | void setup() { 24 | // Start serial communication 25 | Serial.begin(115200); 26 | Serial2.begin(115200, SERIAL_8N1, MODEM_RX, MODEM_TX); 27 | 28 | // Set modem reset and power pins 29 | pinMode(MODEM_RST, OUTPUT); 30 | pinMode(MODEM_POWER, OUTPUT); 31 | 32 | // Restart the modem using the reset pin 33 | digitalWrite(MODEM_RST, LOW); 34 | delay(100); 35 | digitalWrite(MODEM_RST, HIGH); 36 | 37 | // Power up the modem 38 | digitalWrite(MODEM_POWER, HIGH); 39 | delay(2000); 40 | 41 | 42 | 43 | // Unlock your SIM card with a PIN if needed 44 | // modem.simUnlock("1234"); 45 | 46 | // Connect to GPRS 47 | Serial.println("Connecting to GPRS..."); 48 | if (!modem.gprsConnect(apn, gprsUser, gprsPass)) { 49 | Serial.println("GPRS connection failed"); 50 | return; 51 | } 52 | 53 | Serial.println("GPRS connected"); 54 | // Print local IP address 55 | Serial.print("IP address: "); 56 | Serial.println(modem.localIP()); 57 | } 58 | 59 | void loop() { 60 | // Your GPRS code here 61 | // Example: send an HTTP GET request 62 | Serial.println("Sending HTTP GET request..."); 63 | 64 | modem.sendAT("+HTTPPARA=\"URL\",\"http://worldtimeapi.org/api/timezone/Africa/Tunis\""); 65 | delay(1000); 66 | modem.sendAT("+HTTPACTION=0"); 67 | delay(5000); 68 | 69 | String response; 70 | response = modem.waitResponse(); 71 | 72 | Serial.println("Response:"); 73 | Serial.println(response); 74 | 75 | // Wait for some time before the next request 76 | delay(5000); 77 | } 78 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) ranizouaoui ranizouaouicontact@gmail.com 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 6 | 7 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 8 | 9 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 10 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ESP32-Based-IoT-Tracking-System 2 | 3 | ## Overview 4 | Our project aims to develop a Tracking system using the NEO-7M GPS module. This system is designed to collect geolocation coordinates, process them and present them in a way that suits the needs of customers. We aim to offer a complete solution that will enable efficient and accurate management of location data, thus providing an optimal experience for users.The app will provide valuable information to users such as latitude, longitude and immediate alerts in case of extreme conditions. To ensure data consistency and accessibility, we will deploy Docker containers to run the web application and HiveMQ to manage real-time data streams. The data will be saved to the MongoDB database for future analysis. 5 | 6 |
7 | 8 |
9 | 10 | ## Project Map 11 | Our Tracking system uses the NEO-7M GPS module to retrieve real-time GPS data, which is then transmitted to an MQTT (HiveMQ ) server. The web application retrieves data from the server and visualizes it on a geographical map. Simultaneously, the data stream is kept in a MongoDB database for future use. This project provides a comprehensive and efficient solution for real-time tracking and management of location data. 12 | 13 | Note: The ESP32 board starts sending data if it is well configured (from the configuration interface) 14 |
15 | 16 |
17 |

Practically, we didn't work with the gprs module (just Wi-Fi). So, you can implement the code on TTGO or ESP32 board. It is the same

18 | 19 | ## Manual Setup 20 | ### ESP32 board setup 21 | Perform the following steps: 22 | 23 | 1- Download and install Arduino.
24 | 2- Install ESP32 Filesystem Uploader in Arduino IDE.
25 | 3- Edit the source Code (update the broker and the firebase settings).
26 | 4- Install the libraries used in the arduino code.
27 | 5- Upload the configuration interface in spiffs on esp32 board (Go to Tools >ESP32 Data Sketch Upload and wait for the files to be uploaded).
28 | 6- Upload the source Code.
29 | 30 |

You will need to create an account in firebase and HiveMQ to be able to modify the arduino code

31 | 32 | 7- Connect to the "Gps-Tracker" access point.
33 | 8- Configure the gps tracker from the configuration interface (http://192.168.4.1/).
34 |
35 | 36 |
37 |

If the tracker is well configured you will be redirected to this interface

38 |
39 | 40 |
41 | 9- Make the wiring between the board and the gprs module as shown here 42 | 43 | ## Web application setup 44 | 45 |
46 |

Make sure Docker is installed.

47 |
48 | 49 |

You need to update the broker and the firebase settings in backend >server.js and frontend>src>firebase.js

50 |

Spin up the containers

51 | 52 | ``` 53 | docker-compose up -d --build 54 | ``` 55 | Running the command will expose 3 services with the following ports: 56 |
    57 | 58 |
  • Backend - :3000
  • 59 |
  • Frontend - :8080
  • 60 |
  • Mongodb - :27017
  • 61 |
62 | 63 | You can now access the server at http://localhost:8080/. 64 | 65 | ## App preview 66 | 67 |
68 | 69 |
70 |
71 | 72 |
73 |
74 | 75 |
76 | 77 | ## Want more details? 78 | 79 | For more details or if you want to recommend me for other projects. Just contact me on my email: ranizouaouicontact@gmail.com 80 | -------------------------------------------------------------------------------- /backend/.dockerignore: -------------------------------------------------------------------------------- 1 | node_modules -------------------------------------------------------------------------------- /backend/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | # local env files 4 | .env.local 5 | .env.*.local 6 | 7 | # Log files 8 | npm-debug.log* 9 | yarn-debug.log* 10 | yarn-error.log* 11 | pnpm-debug.log* 12 | 13 | # Editor directories and files 14 | .idea 15 | .vscode 16 | *.suo 17 | *.ntvs* 18 | *.njsproj 19 | *.sln 20 | *.sw? 21 | node_modules 22 | -------------------------------------------------------------------------------- /backend/Dockerfile: -------------------------------------------------------------------------------- 1 | # Use an official Node.js runtime as a parent image 2 | FROM node:14 3 | 4 | # Set the working directory to /app 5 | WORKDIR /app 6 | 7 | # Copy package.json and package-lock.json to the working directory 8 | COPY package*.json ./ 9 | 10 | # Install dependencies 11 | RUN npm install 12 | 13 | # Copy the rest of the app to the working directory 14 | COPY . . 15 | 16 | # Expose port 3000 17 | EXPOSE 3000 18 | 19 | # Start the app 20 | CMD ["node", "server.js"] -------------------------------------------------------------------------------- /backend/HiveMQ.js: -------------------------------------------------------------------------------- 1 | // Test file 2 | 3 | var mqtt = require('mqtt') 4 | 5 | var options = { 6 | host: 'XXXXXXXXXX', 7 | port: 8883, 8 | protocol: 'mqtts', 9 | username: 'XXXXXXXXX', 10 | password: 'XXXXXXXXXX' 11 | } 12 | var data = { 13 | temperature: '0', 14 | humidity: '0', 15 | power: '0', 16 | voltage: '0', 17 | current: '0', 18 | lighting: '0' 19 | } 20 | // initialize the MQTT client 21 | var client = mqtt.connect(options); 22 | 23 | // setup the callbacks 24 | client.on('connect', function () { 25 | console.log('Connected'); 26 | }); 27 | 28 | client.on('error', function (error) { 29 | console.log(error); 30 | }); 31 | // Subscribe to multiple topics 32 | client.subscribe(['voltage', 'current', 'power', 'lighting', 'temperature', 'humidity']); 33 | client.on('message', function (topic, message) { 34 | // called each time a message is received 35 | 36 | if (topic == 'voltage') { 37 | data.voltage = message.toString(); 38 | } 39 | if (topic == 'current') { 40 | data.current = message.toString(); 41 | } 42 | if (topic == 'power') { 43 | data.power = message.toString(); 44 | } 45 | if (topic == 'lighting') { 46 | data.lighting = message.toString(); 47 | } 48 | if (topic == 'temperature') { 49 | data.temperature = message.toString(); 50 | } 51 | if (topic == 'humidity') { 52 | data.humidity = message.toString(); 53 | } 54 | }); 55 | 56 | -------------------------------------------------------------------------------- /backend/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "backend", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "keywords": [], 10 | "author": "", 11 | "license": "ISC", 12 | "dependencies": { 13 | "axios": "^1.4.0", 14 | "body-parser": "^1.20.1", 15 | "cors": "^2.8.5", 16 | "express": "^4.18.2", 17 | "mongodb": "^5.5.0", 18 | "mqtt": "^4.3.7", 19 | "nodemon": "^2.0.20", 20 | "shelljs": "^0.8.5" 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /backend/server.js: -------------------------------------------------------------------------------- 1 | //TODO: CHANGE THE HIVREMQ SETTINGS 2 | const express = require('express') 3 | const { MongoClient } = require('mongodb') 4 | const bodyParser = require('body-parser'); 5 | const cors = require("cors"); 6 | const app = express(); 7 | const port = 3000; 8 | const axios = require('axios'); 9 | var mqtt = require('mqtt') 10 | app.use(bodyParser.urlencoded({ extended: false })); 11 | app.use(bodyParser.json()); 12 | app.use(cors()); 13 | var city = 'sousse' 14 | async function getCityName(latitude, longitude) { 15 | try { 16 | const response = await axios.get(`https://nominatim.openstreetmap.org/reverse?format=json&lat=${latitude}&lon=${longitude}`); 17 | const data = response.data; 18 | 19 | if (data.address && data.address.city) { 20 | city = data.address.city; 21 | } else if (data.address && data.address.town) { 22 | city = data.address.town; 23 | } else if (data.address && data.address.village) { 24 | city = data.address.village; 25 | } else { 26 | city = ''; 27 | } 28 | } catch (error) { 29 | console.error('Error:', error); 30 | } 31 | } 32 | // ! Use this link if you work in docker : mongodb://root:example@mongodb:27017/mydatabase?authSource=admin 33 | // ! Use this link if you work in localhost: mongodb://root:example@localhost:27017/mydatabase?authSource=admin 34 | 35 | const client = new MongoClient('mongodb://root:example@mongodb:27017/mydatabase?authSource=admin', { useUnifiedTopology: true }) 36 | const db = client.db('mydatabase'); 37 | const collection = db.collection('greenhouseData'); 38 | client.connect().then(() => { 39 | console.log('Connected to MongoDB') 40 | }).catch(error => { 41 | console.error(error) 42 | }) 43 | var options = { 44 | host: 'xxxxxxxx', 45 | port: 8883, 46 | protocol: 'mqtts', 47 | username: 'xxxxxxxx', 48 | password: 'xxxxxxxx' 49 | } 50 | 51 | var data = { 52 | Latitude: '36.516418', 53 | Longitude: '9.451063', 54 | 55 | } 56 | // initialize the MQTT client 57 | var client1 = mqtt.connect(options); 58 | 59 | // setup the callbacks 60 | client1.on('connect', function () { 61 | console.log('Connected'); 62 | }); 63 | client1.on('error', function (error) { 64 | console.log(error); 65 | }); 66 | 67 | // Subscribe to multiple topics 68 | client1.subscribe(['latitude', 'longitude']); 69 | client1.on('message', function (topic, message) { 70 | // called each time a message is received 71 | 72 | if (topic == 'latitude') { 73 | data.Latitude = message.toString(); 74 | } 75 | if (topic == 'longitude') { 76 | data.Longitude = message.toString(); 77 | } 78 | }); 79 | app.get('/messages', async function (req, res) { 80 | const currentTime = new Date(); 81 | await getCityName(data.Latitude, data.Longitude); 82 | const messageData = { 83 | Latitude: data.Latitude, 84 | Longitude: data.Longitude, 85 | city: city, 86 | Timestamp: currentTime 87 | }; 88 | console.log(messageData); 89 | collection.insertOne(messageData) 90 | .then(result => { 91 | console.log('Data saved to MongoDB:', result); 92 | res.send(messageData); 93 | }) 94 | .catch(error => { 95 | console.error('Error saving data to MongoDB:', error); 96 | res.status(500).send('Error saving data to MongoDB'); 97 | }); 98 | 99 | }) 100 | app.get('/api/history', async function (req, res) { 101 | 102 | const result = await collection.find().toArray(); 103 | console.log(result); 104 | res.send(result); 105 | }); 106 | app.listen(port, () => { 107 | console.log(`Example app listening on port ${port}`) 108 | }) 109 | -------------------------------------------------------------------------------- /conceptionPCB/PCB_PCB_gps-tracker_2023-06-04.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ranizouaoui/ESP32-Based-IoT-Tracking-System/96c806979455f6fcaf8a6591b8451af4efc24e53/conceptionPCB/PCB_PCB_gps-tracker_2023-06-04.pdf -------------------------------------------------------------------------------- /conceptionPCB/SCH_gps-tracker_2023-06-04.json: -------------------------------------------------------------------------------- 1 | { 2 | "editorVersion": "6.5.23", 3 | "docType": "5", 4 | "title": "gps-tracker", 5 | "description": "", 6 | "colors": {}, 7 | "schematics": [ 8 | { 9 | "docType": "1", 10 | "title": "Sheet_1", 11 | "description": "", 12 | "dataStr": { 13 | "head": { 14 | "docType": "1", 15 | "editorVersion": "6.5.23", 16 | "newgId": true, 17 | "c_para": { 18 | "Prefix Start": "1" 19 | }, 20 | "c_spiceCmd": null 21 | }, 22 | "canvas": "CA~1000~1000~#FFFFFF~yes~#CCCCCC~5~1000~1000~line~5~pixel~5~0~0", 23 | "shape": [ 24 | "LIB~0~-806~package`NONE`BOM_Manufacturer Part`?`spicePre`.`~~0~frame_lib_1~~~0~~yes~yes~~~#@$T~N~570.5~-809~0~#000080~Arial~~~~~comment~A~0~start~gge223~0~#@$PT~M 206 -796 L 206 -806 M 206 -10 L 206 0 M 402 -796 L 402 -806 M 402 -10 L 402 0 M 598 -796 L 598 -806 M 598 -10 L 598 0 M 794 -796 L 794 -806 M 794 -10 L 794 0 M 990 -796 L 990 -806 M 990 -10 L 990 0 M 10 -600 L 0 -600 M 1139 -600 L 1149 -600 M 10 -404 L 0 -404 M 1139 -404 L 1149 -404 M 10 -208 L 0 -208 M 1139 -208 L 1149 -208 M 10 -12 L 0 -12 M 1139 -12 L 1149 -12~#880000~1~0~none~gge10~0~frame_tick#@$T~P~571.3125~-817.59375~0~#000080~Arial~~~~~comment~A~0~start~gge220~0~#@$T~L~1.5~-698~0~#880000~~~~~~comment~A~1~start~gge13~0~frame_tick#@$T~L~1140.5~-698~0~#880000~~~~~~comment~A~1~start~gge19~0~frame_tick#@$T~L~1.5~-502~0~#880000~~~~~~comment~B~1~start~gge25~0~frame_tick#@$T~L~1140.5~-502~0~#880000~~~~~~comment~B~1~start~gge31~0~frame_tick#@$T~L~1.5~-306~0~#880000~~~~~~comment~C~1~start~gge37~0~frame_tick#@$T~L~1140.5~-306~0~#880000~~~~~~comment~C~1~start~gge43~0~frame_tick#@$T~L~1.5~-110~0~#880000~~~~~~comment~D~1~start~gge49~0~frame_tick#@$T~L~1140.5~-110~0~#880000~~~~~~comment~D~1~start~gge55~0~frame_tick#@$T~L~108~-797.5~0~#880000~~~~~~comment~1~1~start~gge61~0~frame_tick#@$T~L~108~-1.5~0~#880000~~~~~~comment~1~1~start~gge67~0~frame_tick#@$T~L~304~-797.5~0~#880000~~~~~~comment~2~1~start~gge73~0~frame_tick#@$T~L~304~-1.5~0~#880000~~~~~~comment~2~1~start~gge79~0~frame_tick#@$T~L~500~-797.5~0~#880000~~~~~~comment~3~1~start~gge85~0~frame_tick#@$T~L~500~-1.5~0~#880000~~~~~~comment~3~1~start~gge91~0~frame_tick#@$T~L~696~-797.5~0~#880000~~~~~~comment~4~1~start~gge97~0~frame_tick#@$T~L~696~-1.5~0~#880000~~~~~~comment~4~1~start~gge103~0~frame_tick#@$T~L~892~-797.5~0~#880000~~~~~~comment~5~1~start~gge109~0~frame_tick#@$T~L~892~-1.5~0~#880000~~~~~~comment~5~1~start~gge115~0~frame_tick#@$R~10~-796~~~1129~786~#880000~1~0~none~gge121~0~frame_innerbox#@$R~0~-806~~~1149~806~#880000~1~0~none~gge124~0~frame_outbox#@$R~694.99995~-90~~~444~80~#880000~1~0~none~gge127~0~frame_hitarea#@$PL~695.1 -50.75 1138.63 -50.75~#880000~1~0~none~gge130~0#@$PL~799.63 -30.75 1138.63 -30.75~#880000~1~0~none~gge133~0#@$PL~1059.61 -89.93 1059.63 -50.75~#880000~1~0~none~gge136~0#@$PL~1059.63 -50.75 1059.63 -30.75~#880000~1~0~none~gge139~0#@$T~L~699.99995~-77~0~#880000~~8pt~~~~comment~TITLE:~1~start~gge142~0~pinpart#@$T~L~757.62495~-64.41~0~#0000FF~~10pt~~~~comment~GPS_Tracker~1~start~gge148~0~frame_title#@$T~L~1064.62495~-63.75~0~#880000~~8pt~~~~comment~REV:~1~start~gge154~0~pinpart#@$T~L~1102.62495~-63.75~0~#0000FF~~9pt~~~~comment~1.0~1~start~gge160~0~frame_version#@$T~L~804.62495~-15~0~#880000~~8pt~~~~comment~Date:~1~start~gge166~0~pinpart#@$T~L~851.62495~-14.52~0~#0000FF~~9pt~~~~comment~2023-06-04~1~start~gge172~0~frame_date#@$T~L~1063.62495~-35~0~#880000~~8pt~~~~comment~Sheet:~1~start~gge178~0~pinpart#@$T~L~1108.62495~-34.52~0~#0000FF~~9pt~~~~comment~1/1~1~start~gge184~0~frame_sheet#@$T~L~943.62495~-14.75~0~#880000~~8pt~~~~comment~Drawn By:~1~start~gge190~0~pinpart#@$T~L~1008.63~-14.75~0~#0000FF~~9pt~~~~comment~Oumaima SLEMA~1~start~gge196~0~frame_drawn#@$T~L~804.62495~-36.75~0~#880000~~8pt~~~~comment~Company:~1~start~gge202~0~pinpart#@$T~L~871.24995~-36.64~0~#0000FF~~9pt~~~~comment~MakerLab~1~start~gge208~0~frame_company#@$PL~799.63 -50.75 799.63 -10.75~#880000~1~0~none~gge214~0#@$Pimage~L~1~gge217~0~gge229~693~-46.5~110~35~data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4NCjxzdmcgdmVyc2lvbj0iMS4xIiBpZD0iSkxDRURBIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB4PSIwcHgiIHk9IjBweCIgdmlld0JveD0iMCAwIDIwMDAgNjI5IiBzdHlsZT0iZW5hYmxlLWJhY2tncm91bmQ6IG5ldyAwIDAgMjAwMCA2Mjk7IiB4bWw6c3BhY2U9InByZXNlcnZlIj4NCgk8cmVjdCBzdHlsZT0iZGlzcGxheTogbm9uZTsgZmlsbDogI0ZGRkZGRjsiIHdpZHRoPSIyMDAwIiBoZWlnaHQ9IjYyOSIgLz4NCgk8cmVjdCB4PSIyMjk4IiB5PSItNjc2IiBzdHlsZT0iZGlzcGxheTogbm9uZTsgZmlsbDogI0ZGRkZGRjsiIHdpZHRoPSIyMDAwIiBoZWlnaHQ9IjIwMDAiIC8+DQoJPGRlc2M+Q3JlYXRlZCBieSBYaWFvWGkoYWRtaW5Ac29yYWhhcnUuY29tKS48L2Rlc2M+DQoJPGc+DQoJCTxwYXRoIHN0eWxlPSJmaWxsOiAjNTU4OEZGOyIgZD0iTTE0NzQuNSwxODguN2MtMC4zLDAtMTE4LjMsMC0xMTguMywwbC0zMCwyMTkuM2gxMjMuN2wwLDBjMTAuNC0wLjIsMTguOC04LjcsMTguOC0xOS4xDQoJCQljMC0xMC42LTguNi0xOS4xLTE5LjEtMTkuMWMtMC40LDAtNzYuNywwLjEtNzYuNywwLjFsOC4xLTU4LjFjMCwwLDc4LjMsMC4xLDc5LDAuMWMxMC43LDAsMTkuNC04LjcsMTkuNC0xOS40DQoJCQljMC05LjYtNy0xNy42LTE2LjItMTkuMWgtNzYuOWw2LjMtNDUuNWMwLDAsODEuNS0wLjEsODItMC4xYzEwLjcsMCwxOS40LTguNywxOS40LTE5LjRDMTQ5My45LDE5Ny40LDE0ODUuMiwxODguNywxNDc0LjUsMTg4Ljd6IiAvPg0KCQk8cGF0aCBzdHlsZT0iZmlsbDogIzU1ODhGRjsiIGQ9Ik0xNjg4LjksMjkzLjhjMC0yMS42LTUtNDAuNi0xNC45LTU3LjFjLTkuOS0xNi41LTIyLjktMjguNi0zOC44LTM2LjMNCgkJCWMtMTUuOS03LjctNDAuMS0xMS41LTcyLjctMTEuNWgtMzQuN2wtMzAsMjE5LjNoNjguMmMyOC42LDAsNTAuOS00LjMsNjctMTIuOGMxNi4xLTguNSwyOS41LTIyLDQwLTQwLjUNCgkJCUMxNjgzLjcsMzM2LjIsMTY4OC45LDMxNS44LDE2ODguOSwyOTMuOHogTTE2MzUsMzM5Yy03LjksMTIuMS0xOC40LDIwLjYtMzEuNiwyNS41Yy05LjMsMy40LTI0LjQsNS4zLTQ1LjMsNS4zaC0xMy42bDE5LjMtMTQyLjMNCgkJCWgxMC4zYzE2LjksMCwzMC40LDIuNiw0MC42LDhjMTAuMSw1LjQsMTgsMTIuOSwyMy42LDIyLjdjNS42LDkuOCw4LjQsMjIsOC40LDM2LjVDMTY0Ni45LDMxMi4yLDE2NDIuOSwzMjcsMTYzNSwzMzl6IiAvPg0KCQk8cGF0aCBzdHlsZT0iZmlsbDogIzU1ODhGRjsiIGQ9Ik0xODQ2LjksMjkxLjRsLTI0LDEzLjJjLTIsMTcuMy0xNi43LDMwLjktMzQuNiwzMC45Yy0xOS4yLDAtMzQuOC0xNS42LTM0LjgtMzQuOA0KCQkJYzAtMTkuMiwxNS42LTM0LjgsMzQuOC0zNC44YzcuNCwwLDE0LjMsMi4zLDE5LjksNi4zbDI5LjgtMTYuNGwtMTYuMS02NC43aC0zNGwtMTE2LjEsMjE0LjloNDMuNWwyNC40LTQ1LjdoODUuM2wxMS40LDQ1LjdoMzkuMg0KCQkJTDE4NDYuOSwyOTEuNHoiIC8+DQoJCQk8ZWxsaXBzZSB0cmFuc2Zvcm09Im1hdHJpeCgxLjA2MzczM2UtMDIgLTAuOTk5OSAwLjk5OTkgMS4wNjM3MzNlLTAyIDE0NzAuMDY5NiAyMDg1LjY3MzgpIiBzdHlsZT0iZmlsbDogIzU1ODhGRjsiIGN4PSIxNzg5IiBjeT0iMjk5LjkiIHJ4PSIxMy41IiByeT0iMTMuNSIgLz4NCgkJPHBhdGggc3R5bGU9ImZpbGw6ICM1NTg4RkY7IiBkPSJNMTIxNS41LDM2Mi4zYzIuNSwyLjgsNi4zLDQuNiwxMC4xLDQuNmgwLjVjNy42LDAsMTQtNS43LDE1LTEzLjJsMjAuMy0xNDMuNmgtMjkuMmwtMjAuMSwxNDEuNg0KCQkJQzEyMTEuOCwzNTUuNCwxMjEyLjksMzU5LjQsMTIxNS41LDM2Mi4zeiIgLz4NCgkJPHBhdGggc3R5bGU9ImZpbGw6ICM1NTg4RkY7IiBkPSJNMTI1MC4zLDM3OC40Yy0wLjMsMi4yLTEuNSw0LjYtMy40LDYuNmMtMS44LDEuNy0zLjcsMi41LTYuMSwyLjVoLTE5LjljLTcuNCwwLTE0LDUuOC0xNSwxMy4yDQoJCQlsLTAuMSwwLjVjLTAuNSw0LDAuNyw3LjgsMy4yLDEwLjdjMi41LDIuOCw2LjMsNC42LDEwLjEsNC42aDE5LjljNS40LDAsMTAuMi0xLDE0LjctMy4yYzEzLjgtNS43LDIzLjItMTcuOCwyNS4xLTMyLjdsMjUuMS0xOTMuNg0KCQkJaC0yOC45TDEyNTAuMywzNzguNHoiIC8+DQoJCTxwYXRoIHN0eWxlPSJmaWxsOiAjNTU4OEZGOyIgZD0iTTEyMDYuNywyNTkuOWMzLjYsMCw2LjYtMi45LDYuNi02LjZjMC0wLjctMC4xLTEuMy0wLjMtMS45YzAsMCwwLDAsMC4xLDBsLTEyLjEtNDJsLTAuMS0wLjINCgkJCWMtMy04LjEtNy0xNC4zLTExLjktMTguMWwtMC41LTAuNGMtNS43LTMuNi0xMy4xLTUuNS0yMi43LTUuNWgtMzIuNmMtOS4yLDAtMTYuOSwxLjktMjIuOCw1LjZjLTYuMyw0LTExLjYsOS43LTE1LjgsMTcNCgkJCWMwLDAtMTYuNywyOC0yNS40LDQyLjRsMC4xLDAuMWMtMC41LDAuOS0wLjgsMS45LTAuOCwzYzAsMy42LDIuOSw2LjYsNi42LDYuNmMwLjEsMCwwLjIsMCwwLjIsMGgyMC43YzEuNi0yLjcsMy4zLTUuNCw1LTguMQ0KCQkJbDAuNS0wLjhjNS40LTkuMywxMi4yLTIwLjgsMTcuNS0yOS41bDAuMS0wLjJjMS40LTIuNCwzLjMtNC41LDUuNC01LjhjMS42LTEsNC4xLTEuNSw3LjEtMS41aDMyLjZjMi43LDAsNC44LDAuNCw1LjgsMS4xDQoJCQljMS40LDEuMSwyLjYsMi44LDMuMiw0LjdsMTEuNSw0MGgyMS4xdi0wLjFDMTIwNi4xLDI1OS45LDEyMDYuNCwyNTkuOSwxMjA2LjcsMjU5Ljl6IiAvPg0KCQk8cGF0aCBzdHlsZT0iZmlsbDogIzU1ODhGRjsiIGQ9Ik0xMTczLDI2OC44aC02MC45Yy04LjQsMC0xNi45LDMuMy0yMy45LDkuM2MtNi44LDUuOC0xMS4zLDEzLjYtMTIuOSwyMS45bC0xNC40LDc4LjcNCgkJCWMtMC45LDUuMS0wLjcsMTAsMC41LDE0LjRjMi4yLDkuMiw4LjEsMTYuMywxNi40LDIwYzQsMi4yLDguNSwzLjMsMTQsMy4zaDg0LjJjNy41LDAsMTQuMS01LjYsMTUuNC0xMy4xbDAuMS0wLjUNCgkJCWMwLjctNC0wLjMtNy44LTIuNy0xMC43Yy0yLjQtMi44LTUuOS00LjUtOS45LTQuNWgtODQuMmMtMS44LDAtMy4zLTAuNy00LjUtMmwtMC4yLTAuMmMtMC42LTAuNy0xLjQtMS45LTAuOS00LjdsMTQuNS03OC44DQoJCQljMC4zLTEuNSwwLjctMi4yLDEuOS0zLjFsMC41LTAuNGMwLjctMC43LDEuNC0xLDMuMi0xaDYwLjljMC44LDAsMS4yLDAuMSwxLjIsMC4xbDAuMywwLjRjMC4yLDAuMywwLjUsMC42LDAuMiwybC03LjYsMzMuMg0KCQkJYy0wLjUsMi43LTIuNSw0LjYtNS4xLDQuNkgxMTMyYy03LjQsMC0xNC4yLDUuOC0xNS40LDEzLjFsLTAuMSwwLjdjLTAuNiwzLjcsMC4zLDcuNSwyLjcsMTAuM2MyLjQsMi45LDYuMSw0LjYsOS45LDQuNmgyNy4yDQoJCQljMC44LDAsMS41LDAsMi4zLTAuMWMwLjYsMCwxLjIsMC4xLDEuOCwwLjFjMTYuNSwwLDI4LjctMTAuNSwzMC4zLTI0LjFjMS0zLjcsOS43LTQwLjMsOS43LTQwLjNjMC44LTQuNCwwLjYtOC43LTAuNi0xMi41DQoJCQlDMTE5Ni42LDI3Ni45LDExODYuMiwyNjguOCwxMTczLDI2OC44eiIgLz4NCgkJPHBhdGggc3R5bGU9ImZpbGw6ICM1NTg4RkY7IiBkPSJNMTAxOSwzODcuM0g4MTMuOWwtMi4xLDIyLjRjMCwwLDAsMCwwLjEsMHYwLjFjMCwzLjYsMi45LDYuNyw2LjcsNi43bDAsMGwwLDBoMTk4LjcNCgkJCWM3LjMsMCwxMy44LTUuOCwxNC44LTEzLjJsMC4xLTAuN2MwLjUtNC0wLjctNy45LTMuMi0xMC44QzEwMjYuMywzODksMTAyMi44LDM4Ny4zLDEwMTksMzg3LjN6IiAvPg0KCQk8cGF0aCBzdHlsZT0iZmlsbDogIzU1ODhGRjsiIGQ9Ik05NTguOSwzODFsMS41LDAuNGMxLjIsMC4zLDIuNCwwLjUsMy42LDAuNWwwLDBjNS43LDAsMTEtMy40LDEzLjYtOC43DQoJCQljMTUuNi0zMy41LDI3LjUtODYuMSw0MC4yLTEyOC4ybDAuMS0wLjNjMC4xLTAuMywwLjEtMC41LDAuMi0wLjhoLTMwYy0xMS45LDM5LjMtMjIuNyw4OC43LTM2LjcsMTE4LjdjLTEuNiwzLjYtMS42LDcuNywwLDExLjMNCgkJCUM5NTIuOCwzNzcuMSw5NTUuNCwzNzkuNyw5NTguOSwzODF6IiAvPg0KCQk8cGF0aCBzdHlsZT0iZmlsbDogIzU1ODhGRjsiIGQ9Ik04NzEuOCwzNjcuN2MxLDYuNSw2LjQsMTAuOSwxMy4xLDEwLjljMSwwLDItMC4xLDMtMC4zbDAuMy0wLjFjNy4xLTEuOSwxMS45LTguNCwxMS4yLTE1LjQNCgkJCWwtMTIuMS0xMTYuNkg4NTl2MC4xbDEyLjgsMTIwLjlMODcxLjgsMzY3Ljd6IiAvPg0KCQk8cGF0aCBzdHlsZT0iZmlsbDogIzU1ODhGRjsiIGQ9Ik0xMDI4LjcsMjA1LjVoLTcyLjVsMy44LTI1LjJoLTIyLjdsMCwwYy0wLjEsMC0wLjIsMC0wLjQsMGMtMy4zLDAtNi4xLDIuNS02LjUsNS45bDAsMGwtMy4zLDE5LjMNCgkJCWMwLDAtODcuOSwwLTg4LjQsMC4xbC0xLjksMjAuNWMtMC4xLDAuNC0wLjEsMC44LTAuMSwxLjNjMCwzLjYsMi45LDYuNiw2LjYsNi43djAuMWMzNC43LDAuMSwxODMuOCwwLDE4My44LDBjNy42LDAsMTQtNS42LDE1LTEzDQoJCQlWMjIxYzAuNS00LjEtMC42LTcuOS0zLjEtMTAuOEMxMDM2LjUsMjA3LjEsMTAzMi44LDIwNS41LDEwMjguNywyMDUuNXoiIC8+DQoJCTxwYXRoIHN0eWxlPSJmaWxsOiAjNTU4OEZGOyIgZD0iTTYxNy45LDM1OC41aDIzLjdjMTQuNywwLDIwLjUsNywxNy45LDIxLjhsLTMuMiwxOC42Yy0xLjMsMTQuNy05LDE5LjktMjYuMywyMC41SDYwMHYtMTkuMmgxOC42DQoJCQljNy43LDAsMTAuOS0yLjYsMTIuMi02LjRsMS4zLTUuOGMxLjMtNS4xLTEuOS03LjctOS42LTcuN2gtMTIuOGMtMTIuMiwxOS4yLTMwLjcsMzAuMS02Mi4xLDM5LjdsLTcuNy0xOS4yDQoJCQljMjAuNS02LjQsMjguOC05LjYsNDAuNC0xOS45aC0zMC43bDMuMi0yMS44aDM3LjhjMC0wLjYsMC42LTMuMiwxLjktNi40YzAuNi0yLjYsMy4yLTQuNSw1LjgtNC41aDIyLjRMNjE3LjksMzU4LjV6IiAvPg0KCQk8cGF0aCBzdHlsZT0iZmlsbDogIzU1ODhGRjsiIGQ9Ik01NzIuNSwyMTMuMWwyLjYtMTQuN2g5OC42bDEuMy0xMC4yYzAuNi0zLjIsMy4yLTUuMSw1LjgtNS4xSDcwN2wtMi42LDE1LjRoODguNA0KCQkJYzYuNCwwLDExLjUsNS44LDEwLjksMTIuOGwwLDBjLTAuNiw1LjEtNS4xLDktMTAuOSw5aC05MWwtMS45LDEwLjloNzMuN2M1LjgsMCwxMC4yLDUuMSw5LDEwLjlsMCwwYy0wLjYsNC41LTQuNSw3LjctOSw3LjdINTg5LjENCgkJCWMtMy44LDAtNi40LTMuMi01LjgtN2wxLjktMTEuNWg4My4zbDEuOS0xMC45aC05MS42QzU3NSwyMjAuMiw1NzEuOCwyMTYuMyw1NzIuNSwyMTMuMXoiIC8+DQoJCTxwYXRoIHN0eWxlPSJmaWxsOiAjNTU4OEZGOyIgZD0iTTc3Ni44LDMyMi42aC00Ny40YzAuNi0wLjYsMS45LTEuOSwyLjYtMy4yYzEuOS0zLjgsMy44LTYuNCw0LjUtOWg5LjZjMTYuNywwLDI2LjMtNywyOC4yLTIwLjUNCgkJCWwxLjktMTIuMmMxLjktMTIuOC0zLjgtMTkuMi0xOC42LTE5LjJINjAwYy0xMi44LDAtMjAuNSw3LTIzLjEsMjAuNWwtMS45LDEyLjJjLTEuOSwxMi44LDMuOCwxOS4yLDE4LjYsMTkuMmg5LjYNCgkJCWMwLjYsMy44LDEuMyw2LjQsMS45LDljMC42LDEuMywxLjMsMi42LDEuOSwzLjJoLTU0LjRsLTEuOSwxMi4yYy0wLjYsMy44LDIuNiw3LDUuOCw3aDIxOS43YzQuNSwwLDktMy4yLDkuNi04LjMNCgkJCUM3ODcuNywzMjguNCw3ODIuNiwzMjIuNiw3NzYuOCwzMjIuNnogTTYwMy4yLDI4Ni4xbDAuNi00LjVjMC42LTMuOCwzLjItNS4xLDctNS4xaDEzMC43YzQuNSwwLDYuNCwxLjksNS44LDUuMWwtMC42LDQuNQ0KCQkJYy0wLjYsNS4xLTMuMiw3LjctNy43LDcuN0g2MDguM0M2MDQuNSwyOTMuOCw2MDIuNiwyOTEuMyw2MDMuMiwyODYuMXogTTY5OS45LDMxOS40Yy0wLjYsMS4zLTEuOSwyLjYtMi42LDMuMmgtNTguMw0KCQkJYy0wLjYtMC42LTEuMy0xLjktMS45LTMuMmMtMC42LTMuOC0xLjMtNi40LTEuOS05aDY5LjJDNzAyLjUsMzE1LDcwMS4yLDMxNy41LDY5OS45LDMxOS40eiIgLz4NCgkJPHBhdGggc3R5bGU9ImZpbGw6ICM1NTg4RkY7IiBkPSJNNzU5LjUsMzU0LjdoLTU2LjRjLTE0LjcsMC0yMy4xLDctMjUsMjAuNWwtMy44LDI1Yy0zLjIsMTMuNSwyLjYsMTkuMiwxOC42LDE5LjJoNTQuNA0KCQkJYzE2LTAuNiwyMy43LTYuNCwyNi4zLTIwLjVsMy44LTIzLjFDNzc4LjcsMzYxLjcsNzczLDM1NC43LDc1OS41LDM1NC43eiBNNzQ2LjEsMzgyLjhsLTEuMyw5Yy0wLjYsNS44LTMuOCw5LTksOWgtMjUNCgkJCWMtNywwLTEwLjItMi42LTguMy03LjdsMS4zLTljMC42LTUuOCw0LjUtOSwxMC4yLTloMjYuM0M3NDQuOCwzNzUuMiw3NDcuMywzNzcuNyw3NDYuMSwzODIuOHoiIC8+DQoJPC9nPg0KCTxwYXRoIHN0eWxlPSJmaWxsOiAjNTU4OEZGOyIgZD0iTTQzNC41LDI0OS40Yy03LjMtMTkuMS0xOS0zNi42LTM0LjYtNTAuNWMtMjMuOS0yMS41LTU0LjctMzMuMy04Ni45LTMzLjMNCgkJYy0yNy45LDAtNTQuNCw4LjctNzYuOCwyNS4xYy0xMC44LDcuOS0yMC4yLDE3LjMtMjgsMjcuOWMtNC45LTAuNy05LjgtMS0xNC44LTFjLTI3LjgsMC01My45LDEwLjgtNzMuNCwzMC41DQoJCWMtMTkuNiwxOS42LTMwLjUsNDUuNy0zMC41LDczLjRjMCwyNS44LDkuNSw1MC41LDI2LjgsNjkuN2MxMy44LDE1LjIsMzEuNSwyNS44LDUxLDMwLjljOC41LDI1LjMsMzIuNSw0My42LDYwLjYsNDMuNg0KCQljMzUuMiwwLDYzLjktMjguNyw2My45LTYzLjljMC0yLTAuMS00LjItMC4zLTYuMmw4OS43LTQ3LjFsLTE5LjYtMzRsLTg1LjgsNDUuMWMtMTEuNy0xMy4zLTI4LjktMjEuOC00OC0yMS44DQoJCWMtMjcuOCwwLTUxLjQsMTcuNy02MC4zLDQyLjRjLTIyLjYtOS45LTM4LjQtMzIuNC0zOC40LTU4LjdjMC0zNS4zLDI4LjctNjQuMSw2NC4xLTY0LjFjMTIuNSwwLDI0LjEsMy41LDM0LDkuNw0KCQljMTEuOS0zNS45LDQ1LjctNjEuNyw4NS41LTYxLjdjNDYuMywwLDg0LjUsMzQuOSw4OS41LDc5LjljMS42LTAuMiwzLjItMC4yLDQuOS0wLjJjMjcuOCwwLDUwLjIsMjIuNSw1MC4yLDUwLjINCgkJYzAsMjYuMi0yMC4yLDQ3LjgtNDUuOSw1MGgtMjguOGMtMS4zLTAuMy0yLjYtMC40LTQtMC40Yy0xMSwwLTIwLjEsOS0yMC4xLDIwLjFjMCwxMC41LDguMSwxOS4xLDE4LjQsMjB2MC4yaDM0LjJoMS43bDEuNy0wLjENCgkJYzIyLjQtMS45LDQzLjEtMTIuMSw1OC40LTI4LjdjMTUuNC0xNi43LDIzLjktMzguNCwyMy45LTYxLjFDNDk3LjUsMjk0LjksNDcwLjksMjYwLjgsNDM0LjUsMjQ5LjR6DQoJCU0yMjguMSwzNzYuOQ0KCQljMTMuNiwwLDI0LjcsMTEsMjQuNywyNC43DQoJCWMwLDEzLjYtMTEsMjQuNy0yNC43LDI0LjcNCgkJYy0xMy42LDAtMjQuNy0xMS0yNC43LTI0LjcNCgkJQzIwMy40LDM4OCwyMTQuNSwzNzYuOSwyMjguMSwzNzYuOXoiIC8+DQo8L3N2Zz4NCg==", 25 | "LIB~335~-380~package`TTGO-TCALL-SIM800`Contributor`rommelts coyo`spicePre`U`spiceSymbolName`TTGO-TCALL-SIM800`BOM_Manufacturer Part``~~0~gge15ae65462c778d91~87bde75d958944e8befa93bbb41d5a35~71d845f8e6be4792a66ffba0377696e7~0~~yes~yes~~1615903702~#@$T~N~329.53125~-518~0~#000080~Arial~~~~~comment~TTGO-TCALL-SIM800~1~start~gge3463~0~#@$T~P~329.5390625~-527~0~#000080~Arial~~~~~comment~U1~1~start~gge3469~0~#@$R~268~-515~~~135~270~#840000~1~0~#FFFFC2~gge3475~0~#@$T~L~333~-450~0~#840000~monospace~3.6pt~0.1~Italic~middle~comment~ESP32-WROVER-8~1~middle~gge3478~0~pinpart#@$T~L~328~-480~0~#840000~monospace~4.5pt~0.1~~middle~comment~ESPRESSIF~1~middle~gge3484~0~pinpart#@$T~L~308~-315~270~#840000~monospace~3.6pt~0.1~~middle~comment~SIM800L~1~middle~gge3490~0~pinpart#@$PL~303 -325 303 -300 313 -295 313 -270~#840000~1~0~none~gge3496~0#@$P~show~3~1~258~-480~180~gge3499~0^^258~-480^^M 258 -480 h 10~#840000^^1~272~-476.25~0~3V3~start~monospace~5.8pt~#840000^^1~259~-480.1~0~1~start~monospace~5.8pt~#840000^^0~265~-480^^0~M 268 -477 L 271 -480 L 268 -483#@$P~show~~10~258~-390~180~gge3520~0^^258~-390^^M 258 -390 h 10~#840000^^1~272~-386.25~0~GPIO26~start~monospace~5.8pt~#840000^^1~259~-390.1~0~10~start~monospace~5.8pt~#840000^^0~265~-390^^0~M 268 -387 L 271 -390 L 268 -393#@$P~show~~11~258~-380~180~gge3541~0^^258~-380^^M 258 -380 h 10~#840000^^1~272~-376.25~0~GPIO27~start~monospace~5.8pt~#840000^^1~259~-380.1~0~11~start~monospace~5.8pt~#840000^^0~265~-380^^0~M 268 -377 L 271 -380 L 268 -383#@$P~show~~12~258~-370~180~gge3562~0^^258~-370^^M 258 -370 h 10~#840000^^1~272~-366.25~0~GPIO14~start~monospace~5.8pt~#840000^^1~259~-370.1~0~12~start~monospace~5.8pt~#840000^^0~265~-370^^0~M 268 -367 L 271 -370 L 268 -373#@$P~show~~13~258~-360~180~gge3583~0^^258~-360^^M 258 -360 h 10~#840000^^1~272~-356.25~0~GPIO12~start~monospace~5.8pt~#840000^^1~259~-360.1~0~13~start~monospace~5.8pt~#840000^^0~265~-360^^0~M 268 -357 L 271 -360 L 268 -363#@$P~show~3~14~258~-350~180~gge3604~0^^258~-350^^M 258 -350 h 10~#840000^^1~272~-346.25~0~GND~start~monospace~5.8pt~#840000^^1~259~-350.1~0~14~start~monospace~5.8pt~#840000^^0~265~-350^^0~M 268 -347 L 271 -350 L 268 -353#@$P~show~~15~258~-340~180~gge3625~0^^258~-340^^M 258 -340 h 10~#840000^^1~272~-336.25~0~GPIO13~start~monospace~5.8pt~#840000^^1~259~-340.1~0~15~start~monospace~5.8pt~#840000^^0~265~-340^^0~M 268 -337 L 271 -340 L 268 -343#@$P~show~~16~258~-330~180~gge3646~0^^258~-330^^M 258 -330 h 10~#840000^^1~272~-326.25~0~SD2~start~monospace~5.8pt~#840000^^1~259~-330.1~0~16~start~monospace~5.8pt~#840000^^0~265~-330^^0~M 268 -327 L 271 -330 L 268 -333#@$P~show~~17~258~-320~180~gge3667~0^^258~-320^^M 258 -320 h 10~#840000^^1~272~-316.25~0~SD3~start~monospace~5.8pt~#840000^^1~259~-320.1~0~17~start~monospace~5.8pt~#840000^^0~265~-320^^0~M 268 -317 L 271 -320 L 268 -323#@$P~show~~18~258~-310~180~gge3688~0^^258~-310^^M 258 -310 h 10~#840000^^1~272~-306.25~0~CMD~start~monospace~5.8pt~#840000^^1~259~-310.1~0~18~start~monospace~5.8pt~#840000^^0~265~-310^^0~M 268 -307 L 271 -310 L 268 -313#@$P~show~3~19~258~-300~180~gge3709~0^^258~-300^^M 258 -300 h 10~#840000^^1~272~-296.25~0~5V~start~monospace~5.8pt~#840000^^1~259~-300.1~0~19~start~monospace~5.8pt~#840000^^0~265~-300^^0~M 268 -297 L 271 -300 L 268 -303#@$P~show~3~2~258~-470~180~gge3730~0^^258~-470^^M 258 -470 h 10~#840000^^1~272~-466.25~0~NC~start~monospace~5.8pt~#840000^^1~259~-470.1~0~2~start~monospace~5.8pt~#840000^^0~265~-470^^0~M 268 -467 L 271 -470 L 268 -473#@$P~show~~20~258~-290~180~gge3751~0^^258~-290^^M 258 -290 h 10~#840000^^1~272~-286.25~0~SPK+~start~monospace~5.8pt~#840000^^1~259~-290.1~0~20~start~monospace~5.8pt~#840000^^0~265~-290^^0~M 268 -287 L 271 -290 L 268 -293#@$P~show~~21~258~-280~180~gge3772~0^^258~-280^^M 258 -280 h 10~#840000^^1~272~-276.25~0~SPK-~start~monospace~5.8pt~#840000^^1~259~-280.1~0~21~start~monospace~5.8pt~#840000^^0~265~-280^^0~M 268 -277 L 271 -280 L 268 -283#@$P~show~3~22~413~-480~0~gge3793~0^^413~-480^^M 413 -480 h -10~#840000^^1~399~-476.25~0~GND~end~monospace~5.8pt~#840000^^1~412~-480.1~0~22~end~monospace~5.8pt~#840000^^0~406~-480^^0~M 403 -483 L 400 -480 L 403 -477#@$P~show~~23~413~-470~0~gge3814~0^^413~-470^^M 413 -470 h -10~#840000^^1~399~-466.25~0~GPIO23~end~monospace~5.8pt~#840000^^1~412~-470.1~0~23~end~monospace~5.8pt~#840000^^0~406~-470^^0~M 403 -473 L 400 -470 L 403 -467#@$P~show~~24~413~-460~0~gge3835~0^^413~-460^^M 413 -460 h -10~#840000^^1~399~-456.25~0~GPIO22~end~monospace~5.8pt~#840000^^1~412~-460.1~0~24~end~monospace~5.8pt~#840000^^0~406~-460^^0~M 403 -463 L 400 -460 L 403 -457#@$P~show~~25~413~-450~0~gge3856~0^^413~-450^^M 413 -450 h -10~#840000^^1~399~-446.25~0~TX~end~monospace~5.8pt~#840000^^1~412~-450.1~0~25~end~monospace~5.8pt~#840000^^0~406~-450^^0~M 403 -453 L 400 -450 L 403 -447#@$P~show~~26~413~-440~0~gge3877~0^^413~-440^^M 413 -440 h -10~#840000^^1~399~-436.25~0~RX~end~monospace~5.8pt~#840000^^1~412~-440.1~0~26~end~monospace~5.8pt~#840000^^0~406~-440^^0~M 403 -443 L 400 -440 L 403 -437#@$P~show~~27~413~-430~0~gge3898~0^^413~-430^^M 413 -430 h -10~#840000^^1~399~-426.25~0~GPIO21~end~monospace~5.8pt~#840000^^1~412~-430.1~0~27~end~monospace~5.8pt~#840000^^0~406~-430^^0~M 403 -433 L 400 -430 L 403 -427#@$P~show~3~28~413~-420~0~gge3919~0^^413~-420^^M 413 -420 h -10~#840000^^1~399~-416.25~0~GND~end~monospace~5.8pt~#840000^^1~412~-420.1~0~28~end~monospace~5.8pt~#840000^^0~406~-420^^0~M 403 -423 L 400 -420 L 403 -417#@$P~show~~29~413~-410~0~gge3940~0^^413~-410^^M 413 -410 h -10~#840000^^1~399~-406.25~0~GPIO19~end~monospace~5.8pt~#840000^^1~412~-410.1~0~29~end~monospace~5.8pt~#840000^^0~406~-410^^0~M 403 -413 L 400 -410 L 403 -407#@$P~show~~3~258~-460~180~gge3961~0^^258~-460^^M 258 -460 h 10~#840000^^1~272~-456.25~0~GPIO36~start~monospace~5.8pt~#840000^^1~259~-460.1~0~3~start~monospace~5.8pt~#840000^^0~265~-460^^0~M 268 -457 L 271 -460 L 268 -463#@$P~show~~30~413~-400~0~gge3982~0^^413~-400^^M 413 -400 h -10~#840000^^1~399~-396.25~0~GPIO18~end~monospace~5.8pt~#840000^^1~412~-400.1~0~30~end~monospace~5.8pt~#840000^^0~406~-400^^0~M 403 -403 L 400 -400 L 403 -397#@$P~show~~31~413~-390~0~gge4003~0^^413~-390^^M 413 -390 h -10~#840000^^1~399~-386.25~0~GPIO5~end~monospace~5.8pt~#840000^^1~412~-390.1~0~31~end~monospace~5.8pt~#840000^^0~406~-390^^0~M 403 -393 L 400 -390 L 403 -387#@$P~show~3~32~413~-380~0~gge4024~0^^413~-380^^M 413 -380 h -10~#840000^^1~399~-376.25~0~NC~end~monospace~5.8pt~#840000^^1~412~-380.1~0~32~end~monospace~5.8pt~#840000^^0~406~-380^^0~M 403 -383 L 400 -380 L 403 -377#@$P~show~3~33~413~-370~0~gge4045~0^^413~-370^^M 413 -370 h -10~#840000^^1~399~-366.25~0~NC~end~monospace~5.8pt~#840000^^1~412~-370.1~0~33~end~monospace~5.8pt~#840000^^0~406~-370^^0~M 403 -373 L 400 -370 L 403 -367#@$P~show~~34~413~-360~0~gge4066~0^^413~-360^^M 413 -360 h -10~#840000^^1~399~-356.25~0~GPIO4~end~monospace~5.8pt~#840000^^1~412~-360.1~0~34~end~monospace~5.8pt~#840000^^0~406~-360^^0~M 403 -363 L 400 -360 L 403 -357#@$P~show~~35~413~-350~0~gge4087~0^^413~-350^^M 413 -350 h -10~#840000^^1~399~-346.25~0~GPIO0~end~monospace~5.8pt~#840000^^1~412~-350.1~0~35~end~monospace~5.8pt~#840000^^0~406~-350^^0~M 403 -353 L 400 -350 L 403 -347#@$P~show~~36~413~-340~0~gge4108~0^^413~-340^^M 413 -340 h -10~#840000^^1~399~-336.25~0~GPIO2~end~monospace~5.8pt~#840000^^1~412~-340.1~0~36~end~monospace~5.8pt~#840000^^0~406~-340^^0~M 403 -343 L 400 -340 L 403 -337#@$P~show~~37~413~-330~0~gge4129~0^^413~-330^^M 413 -330 h -10~#840000^^1~399~-326.25~0~GPIO15~end~monospace~5.8pt~#840000^^1~412~-330.1~0~37~end~monospace~5.8pt~#840000^^0~406~-330^^0~M 403 -333 L 400 -330 L 403 -327#@$P~show~~38~413~-320~0~gge4150~0^^413~-320^^M 413 -320 h -10~#840000^^1~399~-316.25~0~SD1~end~monospace~5.8pt~#840000^^1~412~-320.1~0~38~end~monospace~5.8pt~#840000^^0~406~-320^^0~M 403 -323 L 400 -320 L 403 -317#@$P~show~~39~413~-310~0~gge4171~0^^413~-310^^M 413 -310 h -10~#840000^^1~399~-306.25~0~SD0~end~monospace~5.8pt~#840000^^1~412~-310.1~0~39~end~monospace~5.8pt~#840000^^0~406~-310^^0~M 403 -313 L 400 -310 L 403 -307#@$P~show~~4~258~-450~180~gge4192~0^^258~-450^^M 258 -450 h 10~#840000^^1~272~-446.25~0~GPIO39~start~monospace~5.8pt~#840000^^1~259~-450.1~0~4~start~monospace~5.8pt~#840000^^0~265~-450^^0~M 268 -447 L 271 -450 L 268 -453#@$P~show~~40~413~-300~0~gge4213~0^^413~-300^^M 413 -300 h -10~#840000^^1~399~-296.25~0~CLK~end~monospace~5.8pt~#840000^^1~412~-300.1~0~40~end~monospace~5.8pt~#840000^^0~406~-300^^0~M 403 -303 L 400 -300 L 403 -297#@$P~show~~41~413~-290~0~gge4234~0^^413~-290^^M 413 -290 h -10~#840000^^1~399~-286.25~0~MIC-~end~monospace~5.8pt~#840000^^1~412~-290.1~0~41~end~monospace~5.8pt~#840000^^0~406~-290^^0~M 403 -293 L 400 -290 L 403 -287#@$P~show~3~42~413~-280~0~gge4255~0^^413~-280^^M 413 -280 h -10~#840000^^1~399~-276.25~0~MIC+~end~monospace~5.8pt~#840000^^1~412~-280.1~0~42~end~monospace~5.8pt~#840000^^0~406~-280^^0~M 403 -283 L 400 -280 L 403 -277#@$P~show~~5~258~-440~180~gge4276~0^^258~-440^^M 258 -440 h 10~#840000^^1~272~-436.25~0~GPIO34~start~monospace~5.8pt~#840000^^1~259~-440.1~0~5~start~monospace~5.8pt~#840000^^0~265~-440^^0~M 268 -437 L 271 -440 L 268 -443#@$P~show~~6~258~-430~180~gge4297~0^^258~-430^^M 258 -430 h 10~#840000^^1~272~-426.25~0~GPIO35~start~monospace~5.8pt~#840000^^1~259~-430.1~0~6~start~monospace~5.8pt~#840000^^0~265~-430^^0~M 268 -427 L 271 -430 L 268 -433#@$P~show~~7~258~-420~180~gge4318~0^^258~-420^^M 258 -420 h 10~#840000^^1~272~-416.25~0~GPIO32~start~monospace~5.8pt~#840000^^1~259~-420.1~0~7~start~monospace~5.8pt~#840000^^0~265~-420^^0~M 268 -417 L 271 -420 L 268 -423#@$P~show~~8~258~-410~180~gge4339~0^^258~-410^^M 258 -410 h 10~#840000^^1~272~-406.25~0~GPIO33~start~monospace~5.8pt~#840000^^1~259~-410.1~0~8~start~monospace~5.8pt~#840000^^0~265~-410^^0~M 268 -407 L 271 -410 L 268 -413#@$P~show~~9~258~-400~180~gge4360~0^^258~-400^^M 258 -400 h 10~#840000^^1~272~-396.25~0~GPIO25~start~monospace~5.8pt~#840000^^1~259~-400.1~0~9~start~monospace~5.8pt~#840000^^0~265~-400^^0~M 268 -397 L 271 -400 L 268 -403#@$R~318~-255~~~0.1~0.1~#840000~3.9~0~none~gge4381~0~#@$R~373~-370~~~0.1~0.1~#840000~1~0~none~gge4384~0~#@$PL~313 -250 323 -250~#840000~1~0~none~gge4387~0#@$PL~318 -255 323 -255~#840000~3.9~0~none~gge4390~0#@$PL~353 -505 353 -490~#840000~2~0~none~gge4393~0#@$PL~358 -485 358 -480~#840000~1~0~none~gge4396~0#@$PL~363 -490 363 -505~#840000~2~0~none~gge4399~0#@$PL~358 -485 363 -485 363 -480 358 -480~#840000~1~0~none~gge4402~0#@$PL~368 -255 368 -250 398 -250 398 -255~#840000~1~0~none~gge4405~0#@$PL~298 -265 298 -330 348 -330 348 -265 298 -265~#840000~1~0~none~gge4408~0#@$PL~303 -415 303 -510 368 -510 368 -415 303 -415~#840000~1~0~none~gge4411~0#@$PL~313 -250 313 -260 328 -260 328 -250 323 -250~#840000~1~0~none~gge4414~0#@$PL~273 -265 273 -270 273 -275 283 -275 283 -265 273 -265~#840000~1~0~none~gge4417~0#@$PL~308 -485 353 -485 353 -475 363 -475 363 -420 308 -420 308 -485~#840000~1~0~none~gge4420~0#@$PL~368 -270 373 -270 373 -265 368 -265 368 -260 373 -260 373 -255~#840000~1~0~none~gge4423~0#@$PL~373 -255 368 -255 368 -270 368 -275 398 -275 398 -255 398 -250~#840000~1~0~none~gge4426~0#@$PL~363 -505 363 -490 363 -505 343 -505 343 -500 333 -500 333 -505 328 -505 328 -500 323 -500 323 -505 318 -505 318 -500 313 -500 313 -505 308 -505 308 -495~#840000~2~0~none~gge4429~0", 26 | "LIB~525~-220~package`BORNIER2`Contributor`salydu29`timeStamp`1474660645`sourceId`5y8IiSrpn`spicePre`J`spiceSymbolName`Bornier2`BOM_Manufacturer Part``~90~0~gged13ecbe1423a1450~a968821d37264fce9151d2e0d075bcec~4692b4e310584fa28e192efbb31e9cde~0~~yes~yes~~1474660645~#@$T~N~527~-238.796875~0~#000080~Arial~~~~~comment~Bornier2~1~start~gge6574~0~#@$T~P~527~-247.3984375~0~#000080~Arial~~~~~comment~J1~1~start~gge6580~0~#@$R~465~-260~~~60~40~#000000~1~0~none~gge6586~0~#@$P~show~0~1~475~-280~90~gge6589~0^^475~-280^^M 475 -280 v 20~#880000^^1~478~-258~270~VCC~end~~~#0000FF^^1~474~-265~270~1~start~~~#0000FF^^0~475~-263^^0~M 472 -260 L 475 -257 L 478 -260#@$P~show~0~2~515~-280~90~gge6610~0^^515~-280^^M 515 -280 v 20~#880000^^1~518~-258~270~GND~end~~~#0000FF^^1~514~-265~270~2~start~~~#0000FF^^0~515~-263^^0~M 512 -260 L 515 -257 L 518 -260", 27 | "W~475 -280 440 -280 440 -220 225 -220 225 -300 258 -300~#008800~1~0~none~gge6708~0", 28 | "LIB~660~-505~package`GPS-RECEIVER-NEO6M`description`GPS Receiver Module based on NEO-6 device`spicePre`U`spiceSymbolName`GPS-RECEIVER-NEO6M`BOM_Manufacturer Part``~~0~gge52de17c72071ca63~744c0bc262e3468eb82bb175630e6261~a41d61f51c424e46bea6060e7273f04f~0~~yes~yes~~1488188220~#@$T~N~656.5~-561.3984375~0~#000080~Arial~~~~~comment~GPS-RECEIVER-NEO6M~1~start~gge6987~0~#@$T~P~642.8359375~-566.578125~0~#000080~Arial~~~~~comment~U3~1~start~gge6993~0~#@$P~show~4~5~580~-485~180~gge6999~0^^580~-485^^M 580 -485 h 20~#8D2323^^1~603~-482~0~PPS~start~~~#8D2323^^1~594~-486~0~5~end~~~#8D2323^^0~597~-485^^0~M 600 -482 L 603 -485 L 600 -488#@$P~show~4~4~580~-495~180~gge7020~0^^580~-495^^M 580 -495 h 20~#8D2323^^1~603~-492~0~RXD~start~~~#8D2323^^1~594~-496~0~4~end~~~#8D2323^^0~597~-495^^0~M 600 -492 L 603 -495 L 600 -498#@$P~show~0~3~580~-505~180~gge7041~0^^580~-505^^M 580 -505 h 20~#8D2323^^1~603~-502~0~TXD~start~~~#8D2323^^1~594~-506~0~3~end~~~#8D2323^^0~597~-505^^0~M 600 -502 L 603 -505 L 600 -508#@$P~show~0~2~580~-515~180~gge7062~0^^580~-515^^M 580 -515 h 20~#8D2323^^1~603~-512~0~GND~start~~~#8D2323^^1~594~-516~0~2~end~~~#8D2323^^0~597~-515^^0~M 600 -512 L 603 -515 L 600 -518#@$P~show~0~1~580~-525~180~gge7083~0^^580~-525^^M 580 -525 h 20~#8D2323^^1~603~-522~0~VCC~start~~~#8D2323^^1~594~-526~0~1~end~~~#8D2323^^0~597~-525^^0~M 600 -522 L 603 -525 L 600 -528#@$PL~720 -555 720 -455~#8D2323~1~0~none~gge7104~0#@$PL~720 -455 600 -455~#8D2323~1~0~none~gge7107~0#@$PL~600 -455 600 -555~#8D2323~1~0~none~gge7110~0#@$PL~600 -555 720 -555~#8D2323~1~0~none~gge7113~0#@$T~L~700~-545~0~#8D2323~~7~ ~ ~ ~comment~ANT~1~start~gge7116~0~pinpart#@$E~700~-525~10~10~#8D2323~1~0~none~gge7122~0", 29 | "W~258 -480 230 -480 230 -545 565 -545 565 -525 580 -525~#008800~1~0~none~gge7269~0", 30 | "W~580 -515 450 -515 450 -480 413 -480~#008800~1~0~none~gge7272~0", 31 | "W~515 -280 515 -515~#008800~1~0~none~gge7275~0", 32 | "W~413 -360 530 -360 530 -505 580 -505~#008800~1~0~none~gge7279~0", 33 | "LIB~625~-355~package`BOUTTON POUSSOIR FOOTPRINT`BOM_Manufacturer``BOM_Manufacturer Part``BOM_Supplier Part``BOM_Supplier``link``Contributor`Chr2021`spicePre`U`spiceSymbolName`Button Poussoir 6.15x6.15 02`~~0~ggefeaf1e0af1cd1f34~f4272624d96945c39392c1ac9877aac1~8a731219991f4061bcb928446998d99f~0~~yes~yes~d6e963c546314169a3de522c54f26663~1672246821~f8d825fc804c460bb55b58d9b302918f#@$T~N~663.7890625~-381.578125~0~#000080~Arial~~~~~comment~Button Poussoir 6.15x6.15 02~1~start~gge7513~0~#@$T~P~649.0625~-386.578125~0~#000080~Arial~~~~~comment~U2~1~start~gge7519~0~#@$P~show~0~1~605~-355~180~gge7525~0^^605~-355^^M 605 -355 h 20~#880000^^1~617~-342~0~A~start~~~#0000FF^^1~600~-356~0~1~end~~~#0000FF^^0~622~-355^^0~M 625 -352 L 628 -355 L 625 -358#@$P~show~0~2~705~-355~0~gge7546~0^^705~-355^^M 705 -355 h -20~#880000^^1~693~-342~0~D~end~~~#0000FF^^1~710~-356~0~2~start~~~#0000FF^^0~688~-355^^0~M 685 -358 L 682 -355 L 685 -352#@$P~show~0~3~605~-315~180~gge7567~0^^605~-315^^M 605 -315 h 20~#880000^^1~617~-302~0~B~start~~~#0000FF^^1~600~-316~0~3~end~~~#0000FF^^0~622~-315^^0~M 625 -312 L 628 -315 L 625 -318#@$P~show~0~4~705~-315~0~gge7588~0^^705~-315^^M 705 -315 h -20~#880000^^1~693~-302~0~C~end~~~#0000FF^^1~710~-316~0~4~start~~~#0000FF^^0~688~-315^^0~M 685 -318 L 682 -315 L 685 -312#@$PL~625 -365 685 -365~#000000~2~0~none~gge7609~0#@$R~645~-375~~~20~10~#000000~2~0~#CC0000~gge7612~0~#@$PL~655 -365 655 -335~#000000~2~1~none~gge7615~0#@$PL~645 -325 645 -345~#000000~2~0~none~gge7618~0#@$T~L~610~-385~0~#0000FF~~9pt~~~~comment~BP 01~1~start~gge7621~0~pinpart#@$PL~625 -355 685 -355~#FF9900~1~0~none~gge7627~0#@$PL~625 -315 685 -315~#FF9900~1~0~none~gge7630~0#@$PL~645 -335 655 -335~#000000~2~0~none~gge7633~0#@$PL~635 -315 635 -325~#FF9900~1~0~none~gge7636~0#@$PL~635 -345 635 -355~#FF9900~1~0~none~gge7639~0", 34 | "LIB~575~-415~package`LED0603_RED`BOM_Manufacturer`EVERLIGHT(台湾亿光)`BOM_Manufacturer Part`19-217/R6C-AL1M2VY/3T`BOM_Supplier Part`C72044`BOM_Supplier`LCSC`link``Contributor`LCEDA_01`spicePre`L`spiceSymbolName`LED-0603_R`~90~0~gged30afb3a3e194569~1efb3a885b5b4aecb6d41221a8f4d86b~5cbe824183374fac8e4c1ae848199ce3~0~~yes~yes~~1586866965~#@$T~N~585~-402.796875~0~#000080~Arial~~~~~comment~LED-0603_R~1~start~gge7777~0~#@$T~P~585.0078125~-411.3984375~0~#000080~Arial~~~~~comment~LED1~1~start~gge7783~0~#@$PT~M 581 -410 L 575 -420 L 568 -410 Z ~#880000~1~0~#FF0000~gge7789~0~#@$PL~567 -420 583 -420~#880000~1~0~#FF0000~gge7792~0#@$PL~565 -420 561 -424~#880000~1~0~#880000~gge7795~0#@$PL~569 -424 565 -428~#880000~1~0~#880000~gge7798~0#@$PT~M 558 -427 L 560 -423 L 562 -425 Z ~#880000~1~0~#FF0000~gge7801~0~#@$PT~M 562 -431 L 564 -427 L 566 -429 Z ~#880000~1~0~#FF0000~gge7804~0~#@$P~show~0~1~575~-395~270~gge7807~0^^575~-395^^M 575 -395 v -15~#880000^^0~578~-412~270~1~start~~~#0000FF^^0~574~-408~270~1~end~~~#0000FF^^0~575~-407^^0~M 578 -410 L 575 -413 L 572 -410#@$P~show~0~2~575~-435~90~gge7828~0^^575~-435^^M 575 -435 v 15~#880000^^0~578~-418~270~2~end~~~#0000FF^^0~574~-422~270~2~start~~~#0000FF^^0~575~-423^^0~M 572 -420 L 575 -417 L 578 -420", 35 | "LIB~560~-455~package`R0603`nameAlias`Value(Ω)`BOM_Supplier Part``BOM_Supplier``Contributor`LCEDA_Lib`spicePre`R`spiceSymbolName`R_0603_EU`BOM_Manufacturer Part``~~0~gge8af073a7c159dc95~398691f1f785460098bbe5ee6590333c~bb009484ef804a24ac5d18c54b249586~0~~yes~yes~~1586862199~#@$T~N~549.8359375~-461.578125~0~#000080~Arial~~~~~comment~220 Ohm~1~start~gge7941~0~#@$T~P~553.8359375~-471.578125~0~#000080~Arial~~~~~comment~R1~1~start~gge7947~0~#@$R~550~-460~~~20~10~#A00000~1~0~none~gge7953~0~#@$P~show~0~2~580~-455~0~gge7956~0^^580~-455^^M 570 -455 h 10~#800^^0~566~-455~0~2~end~~~#800^^0~574~-459~0~2~start~~~#800^^0~593~-455^^0~M 590 -458 L 587 -455 L 590 -452#@$P~show~0~1~540~-455~180~gge7977~0^^540~-455^^M 550 -455 h -10~#800^^0~554~-455~0~1~start~~~#800^^0~546~-459~0~1~end~~~#800^^0~527~-455^^0~M 530 -452 L 533 -455 L 530 -458", 36 | "W~580 -455 580 -435 575 -435~#008800~1~0~none~gge8061~0", 37 | "W~540 -455 515 -455~#008800~1~0~none~gge8067~0", 38 | "W~575 -395 435 -395 435 -430 413 -430~#008800~1~0~none~gge8071~0", 39 | "LIB~555~-340~package`R0603`nameAlias`Value(Ω)`BOM_Supplier Part``BOM_Supplier``Contributor`LCEDA_Lib`spicePre`R`spiceSymbolName`R_0603_EU`BOM_Manufacturer Part``~~0~ggef276611e249c6237~398691f1f785460098bbe5ee6590333c~bb009484ef804a24ac5d18c54b249586~0~~yes~yes~~1586862199~#@$T~N~529.8359375~-346.578125~0~#000080~Arial~~~~~comment~1k~0~start~gge8218~0~#@$T~P~548.8359375~-356.578125~0~#000080~Arial~~~~~comment~R2~1~start~gge8080~0~#@$R~545~-345~~~20~10~#A00000~1~0~none~gge8086~0~#@$P~show~0~2~575~-340~0~gge8089~0^^575~-340^^M 565 -340 h 10~#800^^0~561~-340~0~2~end~~~#800^^0~569~-344~0~2~start~~~#800^^0~588~-340^^0~M 585 -343 L 582 -340 L 585 -337#@$P~show~0~1~535~-340~180~gge8110~0^^535~-340^^M 545 -340 h -10~#800^^0~549~-340~0~1~start~~~#800^^0~541~-344~0~1~end~~~#800^^0~522~-340^^0~M 525 -337 L 528 -340 L 525 -343", 40 | "W~605 -355 575 -355 575 -340~#008800~1~0~none~gge8194~0", 41 | "W~605 -315 605 -255 820 -255 820 -595 490 -595 490 -545~#008800~1~0~none~gge8197~0", 42 | "W~535 -340 515 -340~#008800~1~0~none~gge8201~0", 43 | "W~413 -380 450 -380 450 -320 590 -320 590 -355~#008800~1~0~none~gge8205~0", 44 | "T~L~535~-325~0~#000080~Arial~~~~~comment~220 Ohm~1~start~gge8212~0~pinpart", 45 | "J~515~-515~2.5~#CC0000~gge7276~0", 46 | "J~515~-455~2.5~#CC0000~gge8068~0", 47 | "J~490~-545~2.5~#CC0000~gge8198~0", 48 | "J~515~-340~2.5~#CC0000~gge8202~0", 49 | "J~590~-355~2.5~#CC0000~gge8206~0" 50 | ], 51 | "BBox": { 52 | "x": 0, 53 | "y": -807.1, 54 | "width": 1149, 55 | "height": 807.2 56 | }, 57 | "colors": {} 58 | } 59 | } 60 | ] 61 | } -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: "3.9" 2 | services: 3 | frontend: 4 | build: ./frontend 5 | container_name: frontend 6 | ports: 7 | - "8080:8080" 8 | depends_on: 9 | - backend 10 | backend: 11 | build: ./backend 12 | container_name: backend 13 | ports: 14 | - "3000:3000" 15 | depends_on: 16 | - mongodb 17 | environment: 18 | - MONGO_URI=mongodb://root:example@mongodb:27017/mydatabase?authSource=admin 19 | mongodb: 20 | image: mongo:latest 21 | command: mongod --bind_ip_all 22 | container_name: mongodb 23 | ports: 24 | - "27017:27017" 25 | volumes: 26 | - ./data:/data/db 27 | environment: 28 | MONGO_INITDB_ROOT_USERNAME: root 29 | MONGO_INITDB_ROOT_PASSWORD: example 30 | -------------------------------------------------------------------------------- /frontend/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | /dist 4 | 5 | 6 | # local env files 7 | .env.local 8 | .env.*.local 9 | 10 | # Log files 11 | npm-debug.log* 12 | yarn-debug.log* 13 | yarn-error.log* 14 | pnpm-debug.log* 15 | 16 | # Editor directories and files 17 | .idea 18 | .vscode 19 | *.suo 20 | *.ntvs* 21 | *.njsproj 22 | *.sln 23 | *.sw? 24 | node_modules 25 | -------------------------------------------------------------------------------- /frontend/Dockerfile: -------------------------------------------------------------------------------- 1 | # Use an official Node.js runtime as a parent image 2 | FROM node:14 3 | 4 | # Set the working directory to /app 5 | WORKDIR /app 6 | 7 | # Copy package.json and package-lock.json to the working directory 8 | COPY package*.json ./ 9 | 10 | # Install dependencies 11 | RUN npm install 12 | 13 | # Copy the rest of the app to the working directory 14 | COPY . . 15 | 16 | # Build the app 17 | RUN npm run build 18 | 19 | # Start the Vue.js app 20 | CMD ["npm", "run", "serve"] -------------------------------------------------------------------------------- /frontend/README.md: -------------------------------------------------------------------------------- 1 | # gps-app 2 | 3 | ## Project setup 4 | ``` 5 | npm install 6 | ``` 7 | 8 | ### Compiles and hot-reloads for development 9 | ``` 10 | npm run serve 11 | ``` 12 | 13 | ### Compiles and minifies for production 14 | ``` 15 | npm run build 16 | ``` 17 | 18 | ### Lints and fixes files 19 | ``` 20 | npm run lint 21 | ``` 22 | 23 | ### Customize configuration 24 | See [Configuration Reference](https://cli.vuejs.org/config/). 25 | -------------------------------------------------------------------------------- /frontend/babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: [ 3 | '@vue/cli-plugin-babel/preset' 4 | ] 5 | } 6 | -------------------------------------------------------------------------------- /frontend/jsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5", 4 | "module": "esnext", 5 | "baseUrl": "./", 6 | "moduleResolution": "node", 7 | "paths": { 8 | "@/*": [ 9 | "src/*" 10 | ] 11 | }, 12 | "lib": [ 13 | "esnext", 14 | "dom", 15 | "dom.iterable", 16 | "scripthost" 17 | ] 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /frontend/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "gps-app", 3 | "version": "0.1.0", 4 | "private": true, 5 | "scripts": { 6 | "serve": "vue-cli-service serve", 7 | "build": "vue-cli-service build", 8 | "lint": "vue-cli-service lint" 9 | }, 10 | "dependencies": { 11 | "@vue-leaflet/vue-leaflet": "^0.9.0", 12 | "aos": "^2.3.4", 13 | "axios": "^1.4.0", 14 | "bootstrap": "^5.2.3", 15 | "bootstrap-icons": "^1.10.5", 16 | "bootstrap-vue": "^2.23.1", 17 | "boxicons": "^2.1.4", 18 | "core-js": "^3.8.3", 19 | "firebase": "^9.9.1", 20 | "glightbox": "^3.2.0", 21 | "isotope-layout": "^3.0.6", 22 | "jquery": "^3.6.4", 23 | "leaflet": "^1.9.4", 24 | "leaflet-geosearch": "^3.8.0", 25 | "moment": "^2.29.4", 26 | "ol": "^7.3.0", 27 | "remixicon": "^3.2.0", 28 | "swiper": "^9.2.4", 29 | "vue": "^3.2.13", 30 | "vue-browser-geolocation": "^1.8.0", 31 | "vue-leaflet": "^0.1.0", 32 | "vue-router": "^4.1.6", 33 | "vue-sidebar-menu": "^5.2.6", 34 | "vue3-google-map": "^0.15.0", 35 | "waypoints": "^4.0.1" 36 | }, 37 | "devDependencies": { 38 | "@babel/core": "^7.12.16", 39 | "@babel/eslint-parser": "^7.12.16", 40 | "@vue/cli-plugin-babel": "~5.0.0", 41 | "@vue/cli-plugin-eslint": "~5.0.0", 42 | "@vue/cli-service": "~5.0.0", 43 | "eslint": "^7.32.0", 44 | "eslint-plugin-vue": "^8.0.3" 45 | }, 46 | "eslintConfig": { 47 | "root": true, 48 | "env": { 49 | "node": true 50 | }, 51 | "extends": [ 52 | "plugin:vue/vue3-essential", 53 | "eslint:recommended" 54 | ], 55 | "parserOptions": { 56 | "parser": "@babel/eslint-parser" 57 | }, 58 | "rules": {} 59 | }, 60 | "browserslist": [ 61 | "> 1%", 62 | "last 2 versions", 63 | "not dead", 64 | "not ie 11" 65 | ] 66 | } 67 | -------------------------------------------------------------------------------- /frontend/public/css/style.css: -------------------------------------------------------------------------------- 1 | /** 2 | * Template Name: Arsha 3 | * Updated: Mar 10 2023 with Bootstrap v5.2.3 4 | * Template URL: https://bootstrapmade.com/arsha-free-bootstrap-html-template-corporate/ 5 | * Author: BootstrapMade.com 6 | * License: https://bootstrapmade.com/license/ 7 | */ 8 | 9 | /*-------------------------------------------------------------- 10 | # General 11 | --------------------------------------------------------------*/ 12 | body { 13 | font-family: "Open Sans", sans-serif; 14 | color: #444444; 15 | } 16 | 17 | a { 18 | color: #47b2e4; 19 | text-decoration: none; 20 | } 21 | 22 | a:hover { 23 | color: #73c5eb; 24 | text-decoration: none; 25 | } 26 | 27 | h1, 28 | h2, 29 | h3, 30 | h4, 31 | h5, 32 | h6 { 33 | font-family: "Jost", sans-serif; 34 | } 35 | 36 | /*-------------------------------------------------------------- 37 | # Preloader 38 | --------------------------------------------------------------*/ 39 | #preloader { 40 | position: fixed; 41 | top: 0; 42 | left: 0; 43 | right: 0; 44 | bottom: 0; 45 | z-index: 9999; 46 | overflow: hidden; 47 | background: #37517e; 48 | } 49 | 50 | #preloader:before { 51 | content: ""; 52 | position: fixed; 53 | top: calc(50% - 30px); 54 | left: calc(50% - 30px); 55 | border: 6px solid #37517e; 56 | border-top-color: #fff; 57 | border-bottom-color: #fff; 58 | border-radius: 50%; 59 | width: 60px; 60 | height: 60px; 61 | animation: animate-preloader 1s linear infinite; 62 | } 63 | 64 | @keyframes animate-preloader { 65 | 0% { 66 | transform: rotate(0deg); 67 | } 68 | 69 | 100% { 70 | transform: rotate(360deg); 71 | } 72 | } 73 | 74 | /*-------------------------------------------------------------- 75 | # Back to top button 76 | --------------------------------------------------------------*/ 77 | .back-to-top { 78 | position: fixed; 79 | visibility: hidden; 80 | opacity: 0; 81 | right: 15px; 82 | bottom: 15px; 83 | z-index: 996; 84 | background: #47b2e4; 85 | width: 40px; 86 | height: 40px; 87 | border-radius: 50px; 88 | transition: all 0.4s; 89 | } 90 | 91 | .back-to-top i { 92 | font-size: 24px; 93 | color: #fff; 94 | line-height: 0; 95 | } 96 | 97 | .back-to-top:hover { 98 | background: #6bc1e9; 99 | color: #fff; 100 | } 101 | 102 | .back-to-top.active { 103 | visibility: visible; 104 | opacity: 1; 105 | } 106 | 107 | /*-------------------------------------------------------------- 108 | # Header 109 | --------------------------------------------------------------*/ 110 | #header { 111 | transition: all 0.5s; 112 | z-index: 997; 113 | padding: 3px 0; 114 | background-color: #37517e; 115 | } 116 | 117 | #header.header-scrolled, 118 | #header.header-inner-pages { 119 | background: rgba(40, 58, 90, 0.9); 120 | } 121 | 122 | #header .logo { 123 | font-size: 30px; 124 | margin: 0; 125 | padding: 0; 126 | line-height: 1; 127 | font-weight: 500; 128 | letter-spacing: 2px; 129 | text-transform: uppercase; 130 | } 131 | 132 | #header .logo a { 133 | color: #fff; 134 | } 135 | 136 | #header .logo img { 137 | max-height: 40px; 138 | } 139 | 140 | /*-------------------------------------------------------------- 141 | # Navigation Menu 142 | --------------------------------------------------------------*/ 143 | /** 144 | * Desktop Navigation 145 | */ 146 | .navbar { 147 | padding: 0; 148 | } 149 | 150 | .navbar ul { 151 | margin: 0; 152 | padding: 0; 153 | display: flex; 154 | list-style: none; 155 | align-items: center; 156 | } 157 | 158 | .navbar li { 159 | position: relative; 160 | } 161 | 162 | .navbar a, 163 | .navbar a:focus { 164 | display: flex; 165 | align-items: center; 166 | justify-content: space-between; 167 | padding: 10px 0 10px 30px; 168 | font-size: 15px; 169 | font-weight: 500; 170 | color: #fff; 171 | white-space: nowrap; 172 | transition: 0.3s; 173 | } 174 | 175 | .navbar a i, 176 | .navbar a:focus i { 177 | font-size: 12px; 178 | line-height: 0; 179 | margin-left: 5px; 180 | } 181 | 182 | .navbar a:hover, 183 | .navbar .active, 184 | .navbar .active:focus, 185 | .navbar li:hover>a { 186 | color: #47b2e4; 187 | } 188 | 189 | .navbar .getstarted, 190 | .navbar .getstarted:focus { 191 | padding: 8px 20px; 192 | margin-left: 30px; 193 | border-radius: 50px; 194 | color: #fff; 195 | font-size: 14px; 196 | border: 2px solid #47b2e4; 197 | font-weight: 600; 198 | } 199 | 200 | .navbar .getstarted:hover, 201 | .navbar .getstarted:focus:hover { 202 | color: #fff; 203 | background: #31a9e1; 204 | } 205 | 206 | .navbar .dropdown ul { 207 | display: block; 208 | position: absolute; 209 | left: 14px; 210 | top: calc(100% + 30px); 211 | margin: 0; 212 | padding: 10px 0; 213 | z-index: 99; 214 | opacity: 0; 215 | visibility: hidden; 216 | background: #fff; 217 | box-shadow: 0px 0px 30px rgba(127, 137, 161, 0.25); 218 | transition: 0.3s; 219 | border-radius: 4px; 220 | } 221 | 222 | .navbar .dropdown ul li { 223 | min-width: 200px; 224 | } 225 | 226 | .navbar .dropdown ul a { 227 | padding: 10px 20px; 228 | font-size: 14px; 229 | text-transform: none; 230 | font-weight: 500; 231 | color: #0c3c53; 232 | } 233 | 234 | .navbar .dropdown ul a i { 235 | font-size: 12px; 236 | } 237 | 238 | .navbar .dropdown ul a:hover, 239 | .navbar .dropdown ul .active:hover, 240 | .navbar .dropdown ul li:hover>a { 241 | color: #47b2e4; 242 | } 243 | 244 | .navbar .dropdown:hover>ul { 245 | opacity: 1; 246 | top: 100%; 247 | visibility: visible; 248 | } 249 | 250 | .navbar .dropdown .dropdown ul { 251 | top: 0; 252 | left: calc(100% - 30px); 253 | visibility: hidden; 254 | } 255 | 256 | .navbar .dropdown .dropdown:hover>ul { 257 | opacity: 1; 258 | top: 0; 259 | left: 100%; 260 | visibility: visible; 261 | } 262 | 263 | @media (max-width: 1366px) { 264 | .navbar .dropdown .dropdown ul { 265 | left: -90%; 266 | } 267 | 268 | .navbar .dropdown .dropdown:hover>ul { 269 | left: -100%; 270 | } 271 | } 272 | 273 | /** 274 | * Mobile Navigation 275 | */ 276 | .mobile-nav-toggle { 277 | color: #fff; 278 | font-size: 28px; 279 | cursor: pointer; 280 | display: none; 281 | line-height: 0; 282 | transition: 0.5s; 283 | } 284 | 285 | .mobile-nav-toggle.bi-x { 286 | color: #fff; 287 | } 288 | 289 | @media (max-width: 991px) { 290 | .mobile-nav-toggle { 291 | display: block; 292 | } 293 | 294 | .navbar ul { 295 | display: none; 296 | } 297 | } 298 | 299 | .navbar-mobile { 300 | position: fixed; 301 | overflow: hidden; 302 | top: 0; 303 | right: 0; 304 | left: 0; 305 | bottom: 0; 306 | background: rgba(40, 58, 90, 0.9); 307 | transition: 0.3s; 308 | z-index: 999; 309 | } 310 | 311 | .navbar-mobile .mobile-nav-toggle { 312 | position: absolute; 313 | top: 15px; 314 | right: 15px; 315 | } 316 | 317 | .navbar-mobile ul { 318 | display: block; 319 | position: absolute; 320 | top: 55px; 321 | right: 15px; 322 | bottom: 15px; 323 | left: 15px; 324 | padding: 10px 0; 325 | border-radius: 10px; 326 | background-color: #fff; 327 | overflow-y: auto; 328 | transition: 0.3s; 329 | } 330 | 331 | .navbar-mobile a, 332 | .navbar-mobile a:focus { 333 | padding: 10px 20px; 334 | font-size: 15px; 335 | color: #37517e; 336 | } 337 | 338 | .navbar-mobile a:hover, 339 | .navbar-mobile .active, 340 | .navbar-mobile li:hover>a { 341 | color: #47b2e4; 342 | } 343 | 344 | .navbar-mobile .getstarted, 345 | .navbar-mobile .getstarted:focus { 346 | margin: 15px; 347 | color: #37517e; 348 | } 349 | 350 | .navbar-mobile .dropdown ul { 351 | position: static; 352 | display: none; 353 | margin: 10px 20px; 354 | padding: 10px 0; 355 | z-index: 99; 356 | opacity: 1; 357 | visibility: visible; 358 | background: #fff; 359 | box-shadow: 0px 0px 30px rgba(127, 137, 161, 0.25); 360 | } 361 | 362 | .navbar-mobile .dropdown ul li { 363 | min-width: 200px; 364 | } 365 | 366 | .navbar-mobile .dropdown ul a { 367 | padding: 10px 20px; 368 | } 369 | 370 | .navbar-mobile .dropdown ul a i { 371 | font-size: 12px; 372 | } 373 | 374 | .navbar-mobile .dropdown ul a:hover, 375 | .navbar-mobile .dropdown ul .active:hover, 376 | .navbar-mobile .dropdown ul li:hover>a { 377 | color: #47b2e4; 378 | } 379 | 380 | .navbar-mobile .dropdown>.dropdown-active { 381 | display: block; 382 | } 383 | 384 | /*-------------------------------------------------------------- 385 | # Hero Section 386 | --------------------------------------------------------------*/ 387 | #hero { 388 | width: 100%; 389 | height: 80vh; 390 | background: #37517e; 391 | } 392 | 393 | #hero .container { 394 | padding-top: 72px; 395 | } 396 | 397 | #hero h1 { 398 | margin: 0 0 10px 0; 399 | font-size: 48px; 400 | font-weight: 700; 401 | line-height: 56px; 402 | color: #fff; 403 | } 404 | 405 | #hero h2 { 406 | color: rgba(255, 255, 255, 0.6); 407 | margin-bottom: 50px; 408 | font-size: 24px; 409 | } 410 | 411 | #hero .btn-get-started { 412 | font-family: "Jost", sans-serif; 413 | font-weight: 500; 414 | font-size: 16px; 415 | letter-spacing: 1px; 416 | display: inline-block; 417 | padding: 10px 28px 11px 28px; 418 | border-radius: 50px; 419 | transition: 0.5s; 420 | margin: 10px 0 0 0; 421 | color: #fff; 422 | background: #47b2e4; 423 | } 424 | 425 | #hero .btn-get-started:hover { 426 | background: #209dd8; 427 | } 428 | 429 | #hero .btn-watch-video { 430 | font-size: 16px; 431 | display: flex; 432 | align-items: center; 433 | transition: 0.5s; 434 | margin: 10px 0 0 25px; 435 | color: #fff; 436 | line-height: 1; 437 | } 438 | 439 | #hero .btn-watch-video i { 440 | line-height: 0; 441 | color: #fff; 442 | font-size: 32px; 443 | transition: 0.3s; 444 | margin-right: 8px; 445 | } 446 | 447 | #hero .btn-watch-video:hover i { 448 | color: #47b2e4; 449 | } 450 | 451 | #hero .animated { 452 | animation: up-down 2s ease-in-out infinite alternate-reverse both; 453 | } 454 | 455 | @media (max-width: 991px) { 456 | #hero { 457 | height: 100vh; 458 | text-align: center; 459 | } 460 | 461 | #hero .animated { 462 | animation: none; 463 | } 464 | 465 | #hero .hero-img { 466 | text-align: center; 467 | } 468 | 469 | #hero .hero-img img { 470 | width: 50%; 471 | } 472 | } 473 | 474 | @media (max-width: 768px) { 475 | #hero h1 { 476 | font-size: 28px; 477 | line-height: 36px; 478 | } 479 | 480 | #hero h2 { 481 | font-size: 18px; 482 | line-height: 24px; 483 | margin-bottom: 30px; 484 | } 485 | 486 | #hero .hero-img img { 487 | width: 70%; 488 | } 489 | } 490 | 491 | @media (max-width: 575px) { 492 | #hero .hero-img img { 493 | width: 80%; 494 | } 495 | 496 | #hero .btn-get-started { 497 | font-size: 16px; 498 | padding: 10px 24px 11px 24px; 499 | } 500 | } 501 | 502 | @keyframes up-down { 503 | 0% { 504 | transform: translateY(10px); 505 | } 506 | 507 | 100% { 508 | transform: translateY(-10px); 509 | } 510 | } 511 | 512 | /*-------------------------------------------------------------- 513 | # Sections General 514 | --------------------------------------------------------------*/ 515 | section { 516 | padding: 60px 0; 517 | overflow: hidden; 518 | } 519 | 520 | .section-bg { 521 | background-color: #f3f5fa; 522 | } 523 | 524 | .section-title { 525 | text-align: center; 526 | padding-bottom: 30px; 527 | } 528 | 529 | .section-title h2 { 530 | font-size: 32px; 531 | font-weight: bold; 532 | text-transform: uppercase; 533 | margin-bottom: 20px; 534 | padding-bottom: 20px; 535 | padding-top: 10px; 536 | position: relative; 537 | color: #37517e; 538 | } 539 | 540 | .section-title h2::before { 541 | content: ""; 542 | position: absolute; 543 | display: block; 544 | width: 120px; 545 | height: 1px; 546 | background: #ddd; 547 | bottom: 1px; 548 | left: calc(50% - 60px); 549 | } 550 | 551 | .section-title h2::after { 552 | content: ""; 553 | position: absolute; 554 | display: block; 555 | width: 40px; 556 | height: 3px; 557 | background: #47b2e4; 558 | bottom: 0; 559 | left: calc(50% - 20px); 560 | } 561 | 562 | .section-title p { 563 | margin-bottom: 0; 564 | } 565 | 566 | /*-------------------------------------------------------------- 567 | # Clients 568 | --------------------------------------------------------------*/ 569 | .clients { 570 | padding: 12px 0; 571 | text-align: center; 572 | } 573 | 574 | .clients img { 575 | max-width: 45%; 576 | transition: all 0.4s ease-in-out; 577 | display: inline-block; 578 | padding: 15px 0; 579 | filter: grayscale(100); 580 | } 581 | 582 | .clients img:hover { 583 | filter: none; 584 | transform: scale(1.1); 585 | } 586 | 587 | @media (max-width: 768px) { 588 | .clients img { 589 | max-width: 40%; 590 | } 591 | } 592 | 593 | /*-------------------------------------------------------------- 594 | # About Us 595 | --------------------------------------------------------------*/ 596 | .about .content h3 { 597 | font-weight: 600; 598 | font-size: 26px; 599 | } 600 | 601 | .about .content ul { 602 | list-style: none; 603 | padding: 0; 604 | } 605 | 606 | .about .content ul li { 607 | padding-left: 28px; 608 | position: relative; 609 | } 610 | 611 | .about .content ul li+li { 612 | margin-top: 10px; 613 | } 614 | 615 | .about .content ul i { 616 | position: absolute; 617 | left: 0; 618 | top: 2px; 619 | font-size: 20px; 620 | color: #47b2e4; 621 | line-height: 1; 622 | } 623 | 624 | .about .content p:last-child { 625 | margin-bottom: 0; 626 | } 627 | 628 | .about .content .btn-learn-more { 629 | font-family: "Poppins", sans-serif; 630 | font-weight: 500; 631 | font-size: 14px; 632 | letter-spacing: 1px; 633 | display: inline-block; 634 | padding: 12px 32px; 635 | border-radius: 4px; 636 | transition: 0.3s; 637 | line-height: 1; 638 | color: #47b2e4; 639 | animation-delay: 0.8s; 640 | margin-top: 6px; 641 | border: 2px solid #47b2e4; 642 | } 643 | 644 | .about .content .btn-learn-more:hover { 645 | background: #47b2e4; 646 | color: #fff; 647 | text-decoration: none; 648 | } 649 | 650 | /*-------------------------------------------------------------- 651 | # Why Us 652 | --------------------------------------------------------------*/ 653 | .why-us .content { 654 | padding: 60px 100px 0 100px; 655 | } 656 | 657 | .why-us .content h3 { 658 | font-weight: 400; 659 | font-size: 34px; 660 | color: #37517e; 661 | } 662 | 663 | .why-us .content h4 { 664 | font-size: 20px; 665 | font-weight: 700; 666 | margin-top: 5px; 667 | } 668 | 669 | .why-us .content p { 670 | font-size: 15px; 671 | color: #848484; 672 | } 673 | 674 | .why-us .img { 675 | background-size: contain; 676 | background-repeat: no-repeat; 677 | background-position: center center; 678 | } 679 | 680 | .why-us .accordion-list { 681 | padding: 0 100px 60px 100px; 682 | } 683 | 684 | .why-us .accordion-list ul { 685 | padding: 0; 686 | list-style: none; 687 | } 688 | 689 | .why-us .accordion-list li+li { 690 | margin-top: 15px; 691 | } 692 | 693 | .why-us .accordion-list li { 694 | padding: 20px; 695 | background: #fff; 696 | border-radius: 4px; 697 | } 698 | 699 | .why-us .accordion-list a { 700 | display: block; 701 | position: relative; 702 | font-family: "Poppins", sans-serif; 703 | font-size: 16px; 704 | line-height: 24px; 705 | font-weight: 500; 706 | padding-right: 30px; 707 | outline: none; 708 | cursor: pointer; 709 | } 710 | 711 | .why-us .accordion-list span { 712 | color: #47b2e4; 713 | font-weight: 600; 714 | font-size: 18px; 715 | padding-right: 10px; 716 | } 717 | 718 | .why-us .accordion-list i { 719 | font-size: 24px; 720 | position: absolute; 721 | right: 0; 722 | top: 0; 723 | } 724 | 725 | .why-us .accordion-list p { 726 | margin-bottom: 0; 727 | padding: 10px 0 0 0; 728 | } 729 | 730 | .why-us .accordion-list .icon-show { 731 | display: none; 732 | } 733 | 734 | .why-us .accordion-list a.collapsed { 735 | color: #343a40; 736 | } 737 | 738 | .why-us .accordion-list a.collapsed:hover { 739 | color: #47b2e4; 740 | } 741 | 742 | .why-us .accordion-list a.collapsed .icon-show { 743 | display: inline-block; 744 | } 745 | 746 | .why-us .accordion-list a.collapsed .icon-close { 747 | display: none; 748 | } 749 | 750 | @media (max-width: 1024px) { 751 | 752 | .why-us .content, 753 | .why-us .accordion-list { 754 | padding-left: 0; 755 | padding-right: 0; 756 | } 757 | } 758 | 759 | @media (max-width: 992px) { 760 | .why-us .img { 761 | min-height: 400px; 762 | } 763 | 764 | .why-us .content { 765 | padding-top: 30px; 766 | } 767 | 768 | .why-us .accordion-list { 769 | padding-bottom: 30px; 770 | } 771 | } 772 | 773 | @media (max-width: 575px) { 774 | .why-us .img { 775 | min-height: 200px; 776 | } 777 | } 778 | 779 | /*-------------------------------------------------------------- 780 | # Skills 781 | --------------------------------------------------------------*/ 782 | .skills .content h3 { 783 | font-weight: 700; 784 | font-size: 32px; 785 | color: #37517e; 786 | font-family: "Poppins", sans-serif; 787 | } 788 | 789 | .skills .content ul { 790 | list-style: none; 791 | padding: 0; 792 | } 793 | 794 | .skills .content ul li { 795 | padding-bottom: 10px; 796 | } 797 | 798 | .skills .content ul i { 799 | font-size: 20px; 800 | padding-right: 4px; 801 | color: #47b2e4; 802 | } 803 | 804 | .skills .content p:last-child { 805 | margin-bottom: 0; 806 | } 807 | 808 | .skills .progress { 809 | height: 60px; 810 | display: block; 811 | background: none; 812 | border-radius: 0; 813 | } 814 | 815 | .skills .progress .skill { 816 | padding: 0; 817 | margin: 0 0 6px 0; 818 | text-transform: uppercase; 819 | display: block; 820 | font-weight: 600; 821 | font-family: "Poppins", sans-serif; 822 | color: #37517e; 823 | } 824 | 825 | .skills .progress .skill .val { 826 | float: right; 827 | font-style: normal; 828 | } 829 | 830 | .skills .progress-bar-wrap { 831 | background: #e8edf5; 832 | height: 10px; 833 | } 834 | 835 | .skills .progress-bar { 836 | width: 1px; 837 | height: 10px; 838 | transition: 0.9s; 839 | background-color: #4668a2; 840 | } 841 | 842 | /*-------------------------------------------------------------- 843 | # Services 844 | --------------------------------------------------------------*/ 845 | .services .icon-box { 846 | box-shadow: 0px 0 25px 0 rgba(0, 0, 0, 0.1); 847 | padding: 50px 30px; 848 | transition: all ease-in-out 0.4s; 849 | background: #fff; 850 | } 851 | 852 | .services .icon-box .icon { 853 | margin-bottom: 10px; 854 | } 855 | 856 | .services .icon-box .icon i { 857 | color: #47b2e4; 858 | font-size: 36px; 859 | transition: 0.3s; 860 | } 861 | 862 | .services .icon-box h4 { 863 | font-weight: 500; 864 | margin-bottom: 15px; 865 | font-size: 24px; 866 | } 867 | 868 | .services .icon-box h4 a { 869 | color: #37517e; 870 | transition: ease-in-out 0.3s; 871 | } 872 | 873 | .services .icon-box p { 874 | line-height: 24px; 875 | font-size: 14px; 876 | margin-bottom: 0; 877 | } 878 | 879 | .services .icon-box:hover { 880 | transform: translateY(-10px); 881 | } 882 | 883 | .services .icon-box:hover h4 a { 884 | color: #47b2e4; 885 | } 886 | 887 | /*-------------------------------------------------------------- 888 | # Cta 889 | --------------------------------------------------------------*/ 890 | .cta { 891 | background: linear-gradient(rgba(40, 58, 90, 0.9), rgba(40, 58, 90, 0.9)), url("../img/cta-bg.jpg") fixed center center; 892 | background-size: cover; 893 | padding: 120px 0; 894 | } 895 | 896 | .cta h3 { 897 | color: #fff; 898 | font-size: 28px; 899 | font-weight: 700; 900 | } 901 | 902 | .cta p { 903 | color: #fff; 904 | } 905 | 906 | .cta .cta-btn { 907 | font-family: "Jost", sans-serif; 908 | font-weight: 500; 909 | font-size: 16px; 910 | letter-spacing: 1px; 911 | display: inline-block; 912 | padding: 12px 40px; 913 | border-radius: 50px; 914 | transition: 0.5s; 915 | margin: 10px; 916 | border: 2px solid #fff; 917 | color: #fff; 918 | } 919 | 920 | .cta .cta-btn:hover { 921 | background: #47b2e4; 922 | border: 2px solid #47b2e4; 923 | } 924 | 925 | @media (max-width: 1024px) { 926 | .cta { 927 | background-attachment: scroll; 928 | } 929 | } 930 | 931 | @media (min-width: 769px) { 932 | .cta .cta-btn-container { 933 | display: flex; 934 | align-items: center; 935 | justify-content: flex-end; 936 | } 937 | } 938 | 939 | /*-------------------------------------------------------------- 940 | # Portfolio 941 | --------------------------------------------------------------*/ 942 | .portfolio #portfolio-flters { 943 | list-style: none; 944 | margin-bottom: 20px; 945 | } 946 | 947 | .portfolio #portfolio-flters li { 948 | cursor: pointer; 949 | display: inline-block; 950 | margin: 10px 5px; 951 | font-size: 15px; 952 | font-weight: 500; 953 | line-height: 1; 954 | color: #444444; 955 | transition: all 0.3s; 956 | padding: 8px 20px; 957 | border-radius: 50px; 958 | font-family: "Poppins", sans-serif; 959 | } 960 | 961 | .portfolio #portfolio-flters li:hover, 962 | .portfolio #portfolio-flters li.filter-active { 963 | background: #47b2e4; 964 | color: #fff; 965 | } 966 | 967 | .portfolio .portfolio-item { 968 | margin-bottom: 30px; 969 | } 970 | 971 | .portfolio .portfolio-item .portfolio-img { 972 | overflow: hidden; 973 | } 974 | 975 | .portfolio .portfolio-item .portfolio-img img { 976 | transition: all 0.6s; 977 | } 978 | 979 | .portfolio .portfolio-item .portfolio-info { 980 | opacity: 0; 981 | position: absolute; 982 | left: 15px; 983 | bottom: 0; 984 | z-index: 3; 985 | right: 15px; 986 | transition: all 0.3s; 987 | background: rgba(55, 81, 126, 0.8); 988 | padding: 10px 15px; 989 | } 990 | 991 | .portfolio .portfolio-item .portfolio-info h4 { 992 | font-size: 18px; 993 | color: #fff; 994 | font-weight: 600; 995 | color: #fff; 996 | margin-bottom: 0px; 997 | } 998 | 999 | .portfolio .portfolio-item .portfolio-info p { 1000 | color: #f9fcfe; 1001 | font-size: 14px; 1002 | margin-bottom: 0; 1003 | } 1004 | 1005 | .portfolio .portfolio-item .portfolio-info .preview-link, 1006 | .portfolio .portfolio-item .portfolio-info .details-link { 1007 | position: absolute; 1008 | right: 40px; 1009 | font-size: 24px; 1010 | top: calc(50% - 18px); 1011 | color: #fff; 1012 | transition: 0.3s; 1013 | } 1014 | 1015 | .portfolio .portfolio-item .portfolio-info .preview-link:hover, 1016 | .portfolio .portfolio-item .portfolio-info .details-link:hover { 1017 | color: #47b2e4; 1018 | } 1019 | 1020 | .portfolio .portfolio-item .portfolio-info .details-link { 1021 | right: 10px; 1022 | } 1023 | 1024 | .portfolio .portfolio-item:hover .portfolio-img img { 1025 | transform: scale(1.15); 1026 | } 1027 | 1028 | .portfolio .portfolio-item:hover .portfolio-info { 1029 | opacity: 1; 1030 | } 1031 | 1032 | /*-------------------------------------------------------------- 1033 | # Portfolio Details 1034 | --------------------------------------------------------------*/ 1035 | .portfolio-details { 1036 | padding-top: 40px; 1037 | } 1038 | 1039 | .portfolio-details .portfolio-details-slider img { 1040 | width: 100%; 1041 | } 1042 | 1043 | .portfolio-details .portfolio-details-slider .swiper-pagination { 1044 | margin-top: 20px; 1045 | position: relative; 1046 | } 1047 | 1048 | .portfolio-details .portfolio-details-slider .swiper-pagination .swiper-pagination-bullet { 1049 | width: 12px; 1050 | height: 12px; 1051 | background-color: #fff; 1052 | opacity: 1; 1053 | border: 1px solid #47b2e4; 1054 | } 1055 | 1056 | .portfolio-details .portfolio-details-slider .swiper-pagination .swiper-pagination-bullet-active { 1057 | background-color: #47b2e4; 1058 | } 1059 | 1060 | .portfolio-details .portfolio-info { 1061 | padding: 30px; 1062 | box-shadow: 0px 0 30px rgba(55, 81, 126, 0.08); 1063 | } 1064 | 1065 | .portfolio-details .portfolio-info h3 { 1066 | font-size: 22px; 1067 | font-weight: 700; 1068 | margin-bottom: 20px; 1069 | padding-bottom: 20px; 1070 | border-bottom: 1px solid #eee; 1071 | } 1072 | 1073 | .portfolio-details .portfolio-info ul { 1074 | list-style: none; 1075 | padding: 0; 1076 | font-size: 15px; 1077 | } 1078 | 1079 | .portfolio-details .portfolio-info ul li+li { 1080 | margin-top: 10px; 1081 | } 1082 | 1083 | .portfolio-details .portfolio-description { 1084 | padding-top: 30px; 1085 | } 1086 | 1087 | .portfolio-details .portfolio-description h2 { 1088 | font-size: 26px; 1089 | font-weight: 700; 1090 | margin-bottom: 20px; 1091 | } 1092 | 1093 | .portfolio-details .portfolio-description p { 1094 | padding: 0; 1095 | } 1096 | 1097 | /*-------------------------------------------------------------- 1098 | # Team 1099 | --------------------------------------------------------------*/ 1100 | .team .member { 1101 | position: relative; 1102 | box-shadow: 0px 2px 15px rgba(0, 0, 0, 0.1); 1103 | padding: 30px; 1104 | border-radius: 5px; 1105 | background: #fff; 1106 | transition: 0.5s; 1107 | height: 100%; 1108 | } 1109 | 1110 | .team .member .pic { 1111 | overflow: hidden; 1112 | width: 180px; 1113 | border-radius: 50%; 1114 | } 1115 | 1116 | .team .member .pic img { 1117 | transition: ease-in-out 0.3s; 1118 | } 1119 | 1120 | .team .member:hover { 1121 | transform: translateY(-10px); 1122 | } 1123 | 1124 | .team .member .member-info { 1125 | padding-left: 30px; 1126 | } 1127 | 1128 | .team .member h4 { 1129 | font-weight: 700; 1130 | margin-bottom: 5px; 1131 | font-size: 20px; 1132 | color: #37517e; 1133 | } 1134 | 1135 | .team .member span { 1136 | display: block; 1137 | font-size: 15px; 1138 | padding-bottom: 10px; 1139 | position: relative; 1140 | font-weight: 500; 1141 | } 1142 | 1143 | .team .member span::after { 1144 | content: ""; 1145 | position: absolute; 1146 | display: block; 1147 | width: 50px; 1148 | height: 1px; 1149 | background: #cbd6e9; 1150 | bottom: 0; 1151 | left: 0; 1152 | } 1153 | 1154 | .team .member p { 1155 | margin: 10px 0 0 0; 1156 | font-size: 14px; 1157 | } 1158 | 1159 | .team .member .social { 1160 | margin-top: 12px; 1161 | display: flex; 1162 | align-items: center; 1163 | justify-content: flex-start; 1164 | } 1165 | 1166 | .team .member .social a { 1167 | transition: ease-in-out 0.3s; 1168 | display: flex; 1169 | align-items: center; 1170 | justify-content: center; 1171 | border-radius: 50px; 1172 | width: 32px; 1173 | height: 32px; 1174 | background: #eff2f8; 1175 | } 1176 | 1177 | .team .member .social a i { 1178 | color: #37517e; 1179 | font-size: 16px; 1180 | margin: 0 2px; 1181 | } 1182 | 1183 | .team .member .social a:hover { 1184 | background: #47b2e4; 1185 | } 1186 | 1187 | .team .member .social a:hover i { 1188 | color: #fff; 1189 | } 1190 | 1191 | .team .member .social a+a { 1192 | margin-left: 8px; 1193 | } 1194 | 1195 | /*-------------------------------------------------------------- 1196 | # Pricing 1197 | --------------------------------------------------------------*/ 1198 | .pricing .row { 1199 | padding-top: 40px; 1200 | } 1201 | 1202 | .pricing .box { 1203 | padding: 60px 40px; 1204 | box-shadow: 0 3px 20px -2px rgba(20, 45, 100, 0.1); 1205 | background: #fff; 1206 | height: 100%; 1207 | border-top: 4px solid #fff; 1208 | border-radius: 5px; 1209 | } 1210 | 1211 | .pricing h3 { 1212 | font-weight: 500; 1213 | margin-bottom: 15px; 1214 | font-size: 20px; 1215 | color: #37517e; 1216 | } 1217 | 1218 | .pricing h4 { 1219 | font-size: 48px; 1220 | color: #37517e; 1221 | font-weight: 400; 1222 | font-family: "Jost", sans-serif; 1223 | margin-bottom: 25px; 1224 | } 1225 | 1226 | .pricing h4 sup { 1227 | font-size: 28px; 1228 | } 1229 | 1230 | .pricing h4 span { 1231 | color: #47b2e4; 1232 | font-size: 18px; 1233 | display: block; 1234 | } 1235 | 1236 | .pricing ul { 1237 | padding: 20px 0; 1238 | list-style: none; 1239 | color: #999; 1240 | text-align: left; 1241 | line-height: 20px; 1242 | } 1243 | 1244 | .pricing ul li { 1245 | padding: 10px 0 10px 30px; 1246 | position: relative; 1247 | } 1248 | 1249 | .pricing ul i { 1250 | color: #28a745; 1251 | font-size: 24px; 1252 | position: absolute; 1253 | left: 0; 1254 | top: 6px; 1255 | } 1256 | 1257 | .pricing ul .na { 1258 | color: #ccc; 1259 | } 1260 | 1261 | .pricing ul .na i { 1262 | color: #ccc; 1263 | } 1264 | 1265 | .pricing ul .na span { 1266 | text-decoration: line-through; 1267 | } 1268 | 1269 | .pricing .buy-btn { 1270 | display: inline-block; 1271 | padding: 12px 35px; 1272 | border-radius: 50px; 1273 | color: #47b2e4; 1274 | transition: none; 1275 | font-size: 16px; 1276 | font-weight: 500; 1277 | font-family: "Jost", sans-serif; 1278 | transition: 0.3s; 1279 | border: 1px solid #47b2e4; 1280 | } 1281 | 1282 | .pricing .buy-btn:hover { 1283 | background: #47b2e4; 1284 | color: #fff; 1285 | } 1286 | 1287 | .pricing .featured { 1288 | border-top-color: #47b2e4; 1289 | } 1290 | 1291 | .pricing .featured .buy-btn { 1292 | background: #47b2e4; 1293 | color: #fff; 1294 | } 1295 | 1296 | .pricing .featured .buy-btn:hover { 1297 | background: #23a3df; 1298 | } 1299 | 1300 | @media (max-width: 992px) { 1301 | .pricing .box { 1302 | max-width: 60%; 1303 | margin: 0 auto 30px auto; 1304 | } 1305 | } 1306 | 1307 | @media (max-width: 767px) { 1308 | .pricing .box { 1309 | max-width: 80%; 1310 | margin: 0 auto 30px auto; 1311 | } 1312 | } 1313 | 1314 | @media (max-width: 420px) { 1315 | .pricing .box { 1316 | max-width: 100%; 1317 | margin: 0 auto 30px auto; 1318 | } 1319 | } 1320 | 1321 | /*-------------------------------------------------------------- 1322 | # Frequently Asked Questions 1323 | --------------------------------------------------------------*/ 1324 | .faq .faq-list { 1325 | padding: 0 100px; 1326 | } 1327 | 1328 | .faq .faq-list ul { 1329 | padding: 0; 1330 | list-style: none; 1331 | } 1332 | 1333 | .faq .faq-list li+li { 1334 | margin-top: 15px; 1335 | } 1336 | 1337 | .faq .faq-list li { 1338 | padding: 20px; 1339 | background: #fff; 1340 | border-radius: 4px; 1341 | position: relative; 1342 | } 1343 | 1344 | .faq .faq-list a { 1345 | display: block; 1346 | position: relative; 1347 | font-family: "Poppins", sans-serif; 1348 | font-size: 16px; 1349 | line-height: 24px; 1350 | font-weight: 500; 1351 | padding: 0 30px; 1352 | outline: none; 1353 | cursor: pointer; 1354 | } 1355 | 1356 | .faq .faq-list .icon-help { 1357 | font-size: 24px; 1358 | position: absolute; 1359 | right: 0; 1360 | left: 20px; 1361 | color: #47b2e4; 1362 | } 1363 | 1364 | .faq .faq-list .icon-show, 1365 | .faq .faq-list .icon-close { 1366 | font-size: 24px; 1367 | position: absolute; 1368 | right: 0; 1369 | top: 0; 1370 | } 1371 | 1372 | .faq .faq-list p { 1373 | margin-bottom: 0; 1374 | padding: 10px 0 0 0; 1375 | } 1376 | 1377 | .faq .faq-list .icon-show { 1378 | display: none; 1379 | } 1380 | 1381 | .faq .faq-list a.collapsed { 1382 | color: #37517e; 1383 | transition: 0.3s; 1384 | } 1385 | 1386 | .faq .faq-list a.collapsed:hover { 1387 | color: #47b2e4; 1388 | } 1389 | 1390 | .faq .faq-list a.collapsed .icon-show { 1391 | display: inline-block; 1392 | } 1393 | 1394 | .faq .faq-list a.collapsed .icon-close { 1395 | display: none; 1396 | } 1397 | 1398 | @media (max-width: 1200px) { 1399 | .faq .faq-list { 1400 | padding: 0; 1401 | } 1402 | } 1403 | 1404 | /*-------------------------------------------------------------- 1405 | # Contact 1406 | --------------------------------------------------------------*/ 1407 | .contact .info { 1408 | border-top: 3px solid #47b2e4; 1409 | border-bottom: 3px solid #47b2e4; 1410 | padding: 30px; 1411 | background: #fff; 1412 | width: 100%; 1413 | box-shadow: 0 0 24px 0 rgba(0, 0, 0, 0.1); 1414 | } 1415 | 1416 | .contact .info i { 1417 | font-size: 20px; 1418 | color: #47b2e4; 1419 | float: left; 1420 | width: 44px; 1421 | height: 44px; 1422 | background: #e7f5fb; 1423 | display: flex; 1424 | justify-content: center; 1425 | align-items: center; 1426 | border-radius: 50px; 1427 | transition: all 0.3s ease-in-out; 1428 | } 1429 | 1430 | .contact .info h4 { 1431 | padding: 0 0 0 60px; 1432 | font-size: 22px; 1433 | font-weight: 600; 1434 | margin-bottom: 5px; 1435 | color: #37517e; 1436 | } 1437 | 1438 | .contact .info p { 1439 | padding: 0 0 10px 60px; 1440 | margin-bottom: 20px; 1441 | font-size: 14px; 1442 | color: #6182ba; 1443 | } 1444 | 1445 | .contact .info .email p { 1446 | padding-top: 5px; 1447 | } 1448 | 1449 | .contact .info .social-links { 1450 | padding-left: 60px; 1451 | } 1452 | 1453 | .contact .info .social-links a { 1454 | font-size: 18px; 1455 | display: inline-block; 1456 | background: #333; 1457 | color: #fff; 1458 | line-height: 1; 1459 | padding: 8px 0; 1460 | border-radius: 50%; 1461 | text-align: center; 1462 | width: 36px; 1463 | height: 36px; 1464 | transition: 0.3s; 1465 | margin-right: 10px; 1466 | } 1467 | 1468 | .contact .info .social-links a:hover { 1469 | background: #47b2e4; 1470 | color: #fff; 1471 | } 1472 | 1473 | .contact .info .email:hover i, 1474 | .contact .info .address:hover i, 1475 | .contact .info .phone:hover i { 1476 | background: #47b2e4; 1477 | color: #fff; 1478 | } 1479 | 1480 | .contact .php-email-form { 1481 | width: 100%; 1482 | border-top: 3px solid #47b2e4; 1483 | border-bottom: 3px solid #47b2e4; 1484 | padding: 30px; 1485 | background: #fff; 1486 | box-shadow: 0 0 24px 0 rgba(0, 0, 0, 0.12); 1487 | } 1488 | 1489 | .contact .php-email-form .form-group { 1490 | padding-bottom: 8px; 1491 | } 1492 | 1493 | .contact .php-email-form .validate { 1494 | display: none; 1495 | color: red; 1496 | margin: 0 0 15px 0; 1497 | font-weight: 400; 1498 | font-size: 13px; 1499 | } 1500 | 1501 | .contact .php-email-form .error-message { 1502 | display: none; 1503 | color: #fff; 1504 | background: #ed3c0d; 1505 | text-align: left; 1506 | padding: 15px; 1507 | font-weight: 600; 1508 | } 1509 | 1510 | .contact .php-email-form .error-message br+br { 1511 | margin-top: 25px; 1512 | } 1513 | 1514 | .contact .php-email-form .sent-message { 1515 | display: none; 1516 | color: #fff; 1517 | background: #18d26e; 1518 | text-align: center; 1519 | padding: 15px; 1520 | font-weight: 600; 1521 | } 1522 | 1523 | .contact .php-email-form .loading { 1524 | display: none; 1525 | background: #fff; 1526 | text-align: center; 1527 | padding: 15px; 1528 | } 1529 | 1530 | .contact .php-email-form .loading:before { 1531 | content: ""; 1532 | display: inline-block; 1533 | border-radius: 50%; 1534 | width: 24px; 1535 | height: 24px; 1536 | margin: 0 10px -6px 0; 1537 | border: 3px solid #18d26e; 1538 | border-top-color: #eee; 1539 | animation: animate-loading 1s linear infinite; 1540 | } 1541 | 1542 | .contact .php-email-form .form-group { 1543 | margin-bottom: 20px; 1544 | } 1545 | 1546 | .contact .php-email-form label { 1547 | padding-bottom: 8px; 1548 | } 1549 | 1550 | .contact .php-email-form input, 1551 | .contact .php-email-form textarea { 1552 | border-radius: 0; 1553 | box-shadow: none; 1554 | font-size: 14px; 1555 | border-radius: 4px; 1556 | } 1557 | 1558 | .contact .php-email-form input:focus, 1559 | .contact .php-email-form textarea:focus { 1560 | border-color: #47b2e4; 1561 | } 1562 | 1563 | .contact .php-email-form input { 1564 | height: 44px; 1565 | } 1566 | 1567 | .contact .php-email-form textarea { 1568 | padding: 10px 12px; 1569 | } 1570 | 1571 | .contact .php-email-form button[type=submit] { 1572 | background: #47b2e4; 1573 | border: 0; 1574 | padding: 12px 34px; 1575 | color: #fff; 1576 | transition: 0.4s; 1577 | border-radius: 50px; 1578 | } 1579 | 1580 | .contact .php-email-form button[type=submit]:hover { 1581 | background: #209dd8; 1582 | } 1583 | 1584 | @keyframes animate-loading { 1585 | 0% { 1586 | transform: rotate(0deg); 1587 | } 1588 | 1589 | 100% { 1590 | transform: rotate(360deg); 1591 | } 1592 | } 1593 | 1594 | /*-------------------------------------------------------------- 1595 | # Breadcrumbs 1596 | --------------------------------------------------------------*/ 1597 | .breadcrumbs { 1598 | padding: 15px 0; 1599 | background: #f3f5fa; 1600 | min-height: 40px; 1601 | margin-top: 72px; 1602 | } 1603 | 1604 | @media (max-width: 992px) { 1605 | .breadcrumbs { 1606 | margin-top: 68px; 1607 | } 1608 | } 1609 | 1610 | .breadcrumbs h2 { 1611 | font-size: 28px; 1612 | font-weight: 600; 1613 | color: #37517e; 1614 | } 1615 | 1616 | .breadcrumbs ol { 1617 | display: flex; 1618 | flex-wrap: wrap; 1619 | list-style: none; 1620 | padding: 0 0 10px 0; 1621 | margin: 0; 1622 | font-size: 14px; 1623 | } 1624 | 1625 | .breadcrumbs ol li+li { 1626 | padding-left: 10px; 1627 | } 1628 | 1629 | .breadcrumbs ol li+li::before { 1630 | display: inline-block; 1631 | padding-right: 10px; 1632 | color: #4668a2; 1633 | content: "/"; 1634 | } 1635 | 1636 | /*-------------------------------------------------------------- 1637 | # Footer 1638 | --------------------------------------------------------------*/ 1639 | #footer { 1640 | font-size: 14px; 1641 | background: #37517e; 1642 | } 1643 | 1644 | #footer .footer-newsletter { 1645 | padding: 50px 0; 1646 | background: #f3f5fa; 1647 | text-align: center; 1648 | font-size: 15px; 1649 | color: #444444; 1650 | } 1651 | 1652 | #footer .footer-newsletter h4 { 1653 | font-size: 24px; 1654 | margin: 0 0 20px 0; 1655 | padding: 0; 1656 | line-height: 1; 1657 | font-weight: 600; 1658 | color: #37517e; 1659 | } 1660 | 1661 | #footer .footer-newsletter form { 1662 | margin-top: 30px; 1663 | background: #fff; 1664 | padding: 6px 10px; 1665 | position: relative; 1666 | border-radius: 50px; 1667 | box-shadow: 0px 2px 15px rgba(0, 0, 0, 0.06); 1668 | text-align: left; 1669 | } 1670 | 1671 | #footer .footer-newsletter form input[type=email] { 1672 | border: 0; 1673 | padding: 4px 8px; 1674 | width: calc(100% - 100px); 1675 | } 1676 | 1677 | #footer .footer-newsletter form input[type=submit] { 1678 | position: absolute; 1679 | top: 0; 1680 | right: 0; 1681 | bottom: 0; 1682 | border: 0; 1683 | background: none; 1684 | font-size: 16px; 1685 | padding: 0 20px; 1686 | background: #47b2e4; 1687 | color: #fff; 1688 | transition: 0.3s; 1689 | border-radius: 50px; 1690 | box-shadow: 0px 2px 15px rgba(0, 0, 0, 0.1); 1691 | } 1692 | 1693 | #footer .footer-newsletter form input[type=submit]:hover { 1694 | background: #209dd8; 1695 | } 1696 | 1697 | #footer .footer-top { 1698 | padding: 60px 0 30px 0; 1699 | background: #fff; 1700 | } 1701 | 1702 | #footer .footer-top .footer-contact { 1703 | margin-bottom: 30px; 1704 | } 1705 | 1706 | #footer .footer-top .footer-contact h3 { 1707 | font-size: 28px; 1708 | margin: 0 0 10px 0; 1709 | padding: 2px 0 2px 0; 1710 | line-height: 1; 1711 | text-transform: uppercase; 1712 | font-weight: 600; 1713 | color: #37517e; 1714 | } 1715 | 1716 | #footer .footer-top .footer-contact p { 1717 | font-size: 14px; 1718 | line-height: 24px; 1719 | margin-bottom: 0; 1720 | font-family: "Jost", sans-serif; 1721 | color: #5e5e5e; 1722 | } 1723 | 1724 | #footer .footer-top h4 { 1725 | font-size: 16px; 1726 | font-weight: bold; 1727 | color: #37517e; 1728 | position: relative; 1729 | padding-bottom: 12px; 1730 | } 1731 | 1732 | #footer .footer-top .footer-links { 1733 | margin-bottom: 30px; 1734 | } 1735 | 1736 | #footer .footer-top .footer-links ul { 1737 | list-style: none; 1738 | padding: 0; 1739 | margin: 0; 1740 | } 1741 | 1742 | #footer .footer-top .footer-links ul i { 1743 | padding-right: 2px; 1744 | color: #47b2e4; 1745 | font-size: 18px; 1746 | line-height: 1; 1747 | } 1748 | 1749 | #footer .footer-top .footer-links ul li { 1750 | padding: 10px 0; 1751 | display: flex; 1752 | align-items: center; 1753 | } 1754 | 1755 | #footer .footer-top .footer-links ul li:first-child { 1756 | padding-top: 0; 1757 | } 1758 | 1759 | #footer .footer-top .footer-links ul a { 1760 | color: #777777; 1761 | transition: 0.3s; 1762 | display: inline-block; 1763 | line-height: 1; 1764 | } 1765 | 1766 | #footer .footer-top .footer-links ul a:hover { 1767 | text-decoration: none; 1768 | color: #47b2e4; 1769 | } 1770 | 1771 | #footer .footer-top .social-links a { 1772 | font-size: 18px; 1773 | display: inline-block; 1774 | background: #47b2e4; 1775 | color: #fff; 1776 | line-height: 1; 1777 | padding: 8px 0; 1778 | margin-right: 4px; 1779 | border-radius: 50%; 1780 | text-align: center; 1781 | width: 36px; 1782 | height: 36px; 1783 | transition: 0.3s; 1784 | } 1785 | 1786 | #footer .footer-top .social-links a:hover { 1787 | background: #209dd8; 1788 | color: #fff; 1789 | text-decoration: none; 1790 | } 1791 | 1792 | #footer .footer-bottom { 1793 | padding-top: 30px; 1794 | padding-bottom: 30px; 1795 | color: #fff; 1796 | } 1797 | 1798 | #footer .copyright { 1799 | float: left; 1800 | } 1801 | 1802 | #footer .credits { 1803 | float: right; 1804 | font-size: 13px; 1805 | } 1806 | 1807 | #footer .credits a { 1808 | transition: 0.3s; 1809 | } 1810 | 1811 | @media (max-width: 768px) { 1812 | #footer .footer-bottom { 1813 | padding-top: 20px; 1814 | padding-bottom: 20px; 1815 | } 1816 | 1817 | #footer .copyright, 1818 | #footer .credits { 1819 | text-align: center; 1820 | float: none; 1821 | } 1822 | 1823 | #footer .credits { 1824 | padding-top: 4px; 1825 | } 1826 | } -------------------------------------------------------------------------------- /frontend/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ranizouaoui/ESP32-Based-IoT-Tracking-System/96c806979455f6fcaf8a6591b8451af4efc24e53/frontend/public/favicon.ico -------------------------------------------------------------------------------- /frontend/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 13 | 14 | 15 | 16 | <%= htmlWebpackPlugin.options.title %> 17 | 18 | 19 | 20 | 21 | 25 | 26 |
27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /frontend/public/js/main.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Template Name: Arsha 3 | * Updated: Mar 10 2023 with Bootstrap v5.2.3 4 | * Template URL: https://bootstrapmade.com/arsha-free-bootstrap-html-template-corporate/ 5 | * Author: BootstrapMade.com 6 | * License: https://bootstrapmade.com/license/ 7 | */ 8 | 9 | (function() { 10 | "use strict"; 11 | 12 | /** 13 | * Easy selector helper function 14 | */ 15 | const select = (el, all = false) => { 16 | el = el.trim() 17 | if (all) { 18 | return [...document.querySelectorAll(el)] 19 | } else { 20 | return document.querySelector(el) 21 | } 22 | } 23 | 24 | /** 25 | * Easy event listener function 26 | */ 27 | const on = (type, el, listener, all = false) => { 28 | let selectEl = select(el, all) 29 | if (selectEl) { 30 | if (all) { 31 | selectEl.forEach(e => e.addEventListener(type, listener)) 32 | } else { 33 | selectEl.addEventListener(type, listener) 34 | } 35 | } 36 | } 37 | 38 | /** 39 | * Easy on scroll event listener 40 | */ 41 | const onscroll = (el, listener) => { 42 | el.addEventListener('scroll', listener) 43 | } 44 | 45 | /** 46 | * Navbar links active state on scroll 47 | */ 48 | let navbarlinks = select('#navbar .scrollto', true) 49 | const navbarlinksActive = () => { 50 | let position = window.scrollY + 200 51 | navbarlinks.forEach(navbarlink => { 52 | if (!navbarlink.hash) return 53 | let section = select(navbarlink.hash) 54 | if (!section) return 55 | if (position >= section.offsetTop && position <= (section.offsetTop + section.offsetHeight)) { 56 | navbarlink.classList.add('active') 57 | } else { 58 | navbarlink.classList.remove('active') 59 | } 60 | }) 61 | } 62 | window.addEventListener('load', navbarlinksActive) 63 | onscroll(document, navbarlinksActive) 64 | 65 | /** 66 | * Scrolls to an element with header offset 67 | */ 68 | const scrollto = (el) => { 69 | let header = select('#header') 70 | let offset = header.offsetHeight 71 | 72 | let elementPos = select(el).offsetTop 73 | window.scrollTo({ 74 | top: elementPos - offset, 75 | behavior: 'smooth' 76 | }) 77 | } 78 | 79 | /** 80 | * Toggle .header-scrolled class to #header when page is scrolled 81 | */ 82 | let selectHeader = select('#header') 83 | if (selectHeader) { 84 | const headerScrolled = () => { 85 | if (window.scrollY > 100) { 86 | selectHeader.classList.add('header-scrolled') 87 | } else { 88 | selectHeader.classList.remove('header-scrolled') 89 | } 90 | } 91 | window.addEventListener('load', headerScrolled) 92 | onscroll(document, headerScrolled) 93 | } 94 | 95 | /** 96 | * Back to top button 97 | */ 98 | let backtotop = select('.back-to-top') 99 | if (backtotop) { 100 | const toggleBacktotop = () => { 101 | if (window.scrollY > 100) { 102 | backtotop.classList.add('active') 103 | } else { 104 | backtotop.classList.remove('active') 105 | } 106 | } 107 | window.addEventListener('load', toggleBacktotop) 108 | onscroll(document, toggleBacktotop) 109 | } 110 | 111 | /** 112 | * Mobile nav toggle 113 | */ 114 | on('click', '.mobile-nav-toggle', function(e) { 115 | select('#navbar').classList.toggle('navbar-mobile') 116 | this.classList.toggle('bi-list') 117 | this.classList.toggle('bi-x') 118 | }) 119 | 120 | /** 121 | * Mobile nav dropdowns activate 122 | */ 123 | on('click', '.navbar .dropdown > a', function(e) { 124 | if (select('#navbar').classList.contains('navbar-mobile')) { 125 | e.preventDefault() 126 | this.nextElementSibling.classList.toggle('dropdown-active') 127 | } 128 | }, true) 129 | 130 | /** 131 | * Scrool with ofset on links with a class name .scrollto 132 | */ 133 | on('click', '.scrollto', function(e) { 134 | if (select(this.hash)) { 135 | e.preventDefault() 136 | 137 | let navbar = select('#navbar') 138 | if (navbar.classList.contains('navbar-mobile')) { 139 | navbar.classList.remove('navbar-mobile') 140 | let navbarToggle = select('.mobile-nav-toggle') 141 | navbarToggle.classList.toggle('bi-list') 142 | navbarToggle.classList.toggle('bi-x') 143 | } 144 | scrollto(this.hash) 145 | } 146 | }, true) 147 | 148 | /** 149 | * Scroll with ofset on page load with hash links in the url 150 | */ 151 | window.addEventListener('load', () => { 152 | if (window.location.hash) { 153 | if (select(window.location.hash)) { 154 | scrollto(window.location.hash) 155 | } 156 | } 157 | }); 158 | 159 | /** 160 | * Preloader 161 | */ 162 | let preloader = select('#preloader'); 163 | if (preloader) { 164 | window.addEventListener('load', () => { 165 | preloader.remove() 166 | }); 167 | } 168 | 169 | /** 170 | * Initiate glightbox 171 | */ 172 | const glightbox = GLightbox({ 173 | selector: '.glightbox' 174 | }); 175 | 176 | /** 177 | * Skills animation 178 | */ 179 | let skilsContent = select('.skills-content'); 180 | if (skilsContent) { 181 | new Waypoint({ 182 | element: skilsContent, 183 | offset: '80%', 184 | handler: function(direction) { 185 | let progress = select('.progress .progress-bar', true); 186 | progress.forEach((el) => { 187 | el.style.width = el.getAttribute('aria-valuenow') + '%' 188 | }); 189 | } 190 | }) 191 | } 192 | 193 | /** 194 | * Porfolio isotope and filter 195 | */ 196 | window.addEventListener('load', () => { 197 | let portfolioContainer = select('.portfolio-container'); 198 | if (portfolioContainer) { 199 | let portfolioIsotope = new Isotope(portfolioContainer, { 200 | itemSelector: '.portfolio-item' 201 | }); 202 | 203 | let portfolioFilters = select('#portfolio-flters li', true); 204 | 205 | on('click', '#portfolio-flters li', function(e) { 206 | e.preventDefault(); 207 | portfolioFilters.forEach(function(el) { 208 | el.classList.remove('filter-active'); 209 | }); 210 | this.classList.add('filter-active'); 211 | 212 | portfolioIsotope.arrange({ 213 | filter: this.getAttribute('data-filter') 214 | }); 215 | portfolioIsotope.on('arrangeComplete', function() { 216 | AOS.refresh() 217 | }); 218 | }, true); 219 | } 220 | 221 | }); 222 | 223 | /** 224 | * Initiate portfolio lightbox 225 | */ 226 | const portfolioLightbox = GLightbox({ 227 | selector: '.portfolio-lightbox' 228 | }); 229 | 230 | /** 231 | * Portfolio details slider 232 | */ 233 | new Swiper('.portfolio-details-slider', { 234 | speed: 400, 235 | loop: true, 236 | autoplay: { 237 | delay: 5000, 238 | disableOnInteraction: false 239 | }, 240 | pagination: { 241 | el: '.swiper-pagination', 242 | type: 'bullets', 243 | clickable: true 244 | } 245 | }); 246 | 247 | /** 248 | * Animation on scroll 249 | */ 250 | window.addEventListener('load', () => { 251 | AOS.init({ 252 | duration: 1000, 253 | easing: "ease-in-out", 254 | once: true, 255 | mirror: false 256 | }); 257 | }); 258 | 259 | })() 260 | -------------------------------------------------------------------------------- /frontend/src/App.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /frontend/src/assets/1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ranizouaoui/ESP32-Based-IoT-Tracking-System/96c806979455f6fcaf8a6591b8451af4efc24e53/frontend/src/assets/1.png -------------------------------------------------------------------------------- /frontend/src/assets/3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ranizouaoui/ESP32-Based-IoT-Tracking-System/96c806979455f6fcaf8a6591b8451af4efc24e53/frontend/src/assets/3.jpg -------------------------------------------------------------------------------- /frontend/src/assets/3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ranizouaoui/ESP32-Based-IoT-Tracking-System/96c806979455f6fcaf8a6591b8451af4efc24e53/frontend/src/assets/3.png -------------------------------------------------------------------------------- /frontend/src/assets/GPS.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ranizouaoui/ESP32-Based-IoT-Tracking-System/96c806979455f6fcaf8a6591b8451af4efc24e53/frontend/src/assets/GPS.png -------------------------------------------------------------------------------- /frontend/src/assets/cc.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ranizouaoui/ESP32-Based-IoT-Tracking-System/96c806979455f6fcaf8a6591b8451af4efc24e53/frontend/src/assets/cc.jpg -------------------------------------------------------------------------------- /frontend/src/assets/cone.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ranizouaoui/ESP32-Based-IoT-Tracking-System/96c806979455f6fcaf8a6591b8451af4efc24e53/frontend/src/assets/cone.jpg -------------------------------------------------------------------------------- /frontend/src/assets/flotte.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ranizouaoui/ESP32-Based-IoT-Tracking-System/96c806979455f6fcaf8a6591b8451af4efc24e53/frontend/src/assets/flotte.png -------------------------------------------------------------------------------- /frontend/src/assets/image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ranizouaoui/ESP32-Based-IoT-Tracking-System/96c806979455f6fcaf8a6591b8451af4efc24e53/frontend/src/assets/image.png -------------------------------------------------------------------------------- /frontend/src/assets/img.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ranizouaoui/ESP32-Based-IoT-Tracking-System/96c806979455f6fcaf8a6591b8451af4efc24e53/frontend/src/assets/img.png -------------------------------------------------------------------------------- /frontend/src/assets/img/3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ranizouaoui/ESP32-Based-IoT-Tracking-System/96c806979455f6fcaf8a6591b8451af4efc24e53/frontend/src/assets/img/3.png -------------------------------------------------------------------------------- /frontend/src/assets/img/apple-touch-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ranizouaoui/ESP32-Based-IoT-Tracking-System/96c806979455f6fcaf8a6591b8451af4efc24e53/frontend/src/assets/img/apple-touch-icon.png -------------------------------------------------------------------------------- /frontend/src/assets/img/clients/client-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ranizouaoui/ESP32-Based-IoT-Tracking-System/96c806979455f6fcaf8a6591b8451af4efc24e53/frontend/src/assets/img/clients/client-1.png -------------------------------------------------------------------------------- /frontend/src/assets/img/clients/client-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ranizouaoui/ESP32-Based-IoT-Tracking-System/96c806979455f6fcaf8a6591b8451af4efc24e53/frontend/src/assets/img/clients/client-2.png -------------------------------------------------------------------------------- /frontend/src/assets/img/clients/client-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ranizouaoui/ESP32-Based-IoT-Tracking-System/96c806979455f6fcaf8a6591b8451af4efc24e53/frontend/src/assets/img/clients/client-3.png -------------------------------------------------------------------------------- /frontend/src/assets/img/clients/client-5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ranizouaoui/ESP32-Based-IoT-Tracking-System/96c806979455f6fcaf8a6591b8451af4efc24e53/frontend/src/assets/img/clients/client-5.png -------------------------------------------------------------------------------- /frontend/src/assets/img/clients/client-6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ranizouaoui/ESP32-Based-IoT-Tracking-System/96c806979455f6fcaf8a6591b8451af4efc24e53/frontend/src/assets/img/clients/client-6.png -------------------------------------------------------------------------------- /frontend/src/assets/img/clients/client-7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ranizouaoui/ESP32-Based-IoT-Tracking-System/96c806979455f6fcaf8a6591b8451af4efc24e53/frontend/src/assets/img/clients/client-7.png -------------------------------------------------------------------------------- /frontend/src/assets/img/cta-bg.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ranizouaoui/ESP32-Based-IoT-Tracking-System/96c806979455f6fcaf8a6591b8451af4efc24e53/frontend/src/assets/img/cta-bg.jpg -------------------------------------------------------------------------------- /frontend/src/assets/img/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ranizouaoui/ESP32-Based-IoT-Tracking-System/96c806979455f6fcaf8a6591b8451af4efc24e53/frontend/src/assets/img/favicon.png -------------------------------------------------------------------------------- /frontend/src/assets/img/gps.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ranizouaoui/ESP32-Based-IoT-Tracking-System/96c806979455f6fcaf8a6591b8451af4efc24e53/frontend/src/assets/img/gps.jpg -------------------------------------------------------------------------------- /frontend/src/assets/img/hero-img.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ranizouaoui/ESP32-Based-IoT-Tracking-System/96c806979455f6fcaf8a6591b8451af4efc24e53/frontend/src/assets/img/hero-img.png -------------------------------------------------------------------------------- /frontend/src/assets/img/portfolio/portfolio-1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ranizouaoui/ESP32-Based-IoT-Tracking-System/96c806979455f6fcaf8a6591b8451af4efc24e53/frontend/src/assets/img/portfolio/portfolio-1.jpg -------------------------------------------------------------------------------- /frontend/src/assets/img/portfolio/portfolio-2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ranizouaoui/ESP32-Based-IoT-Tracking-System/96c806979455f6fcaf8a6591b8451af4efc24e53/frontend/src/assets/img/portfolio/portfolio-2.jpg -------------------------------------------------------------------------------- /frontend/src/assets/img/portfolio/portfolio-3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ranizouaoui/ESP32-Based-IoT-Tracking-System/96c806979455f6fcaf8a6591b8451af4efc24e53/frontend/src/assets/img/portfolio/portfolio-3.jpg -------------------------------------------------------------------------------- /frontend/src/assets/img/portfolio/portfolio-4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ranizouaoui/ESP32-Based-IoT-Tracking-System/96c806979455f6fcaf8a6591b8451af4efc24e53/frontend/src/assets/img/portfolio/portfolio-4.jpg -------------------------------------------------------------------------------- /frontend/src/assets/img/portfolio/portfolio-5.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ranizouaoui/ESP32-Based-IoT-Tracking-System/96c806979455f6fcaf8a6591b8451af4efc24e53/frontend/src/assets/img/portfolio/portfolio-5.jpg -------------------------------------------------------------------------------- /frontend/src/assets/img/portfolio/portfolio-6.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ranizouaoui/ESP32-Based-IoT-Tracking-System/96c806979455f6fcaf8a6591b8451af4efc24e53/frontend/src/assets/img/portfolio/portfolio-6.jpg -------------------------------------------------------------------------------- /frontend/src/assets/img/portfolio/portfolio-7.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ranizouaoui/ESP32-Based-IoT-Tracking-System/96c806979455f6fcaf8a6591b8451af4efc24e53/frontend/src/assets/img/portfolio/portfolio-7.jpg -------------------------------------------------------------------------------- /frontend/src/assets/img/portfolio/portfolio-8.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ranizouaoui/ESP32-Based-IoT-Tracking-System/96c806979455f6fcaf8a6591b8451af4efc24e53/frontend/src/assets/img/portfolio/portfolio-8.jpg -------------------------------------------------------------------------------- /frontend/src/assets/img/portfolio/portfolio-9.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ranizouaoui/ESP32-Based-IoT-Tracking-System/96c806979455f6fcaf8a6591b8451af4efc24e53/frontend/src/assets/img/portfolio/portfolio-9.jpg -------------------------------------------------------------------------------- /frontend/src/assets/img/portfolio/portfolio-details-1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ranizouaoui/ESP32-Based-IoT-Tracking-System/96c806979455f6fcaf8a6591b8451af4efc24e53/frontend/src/assets/img/portfolio/portfolio-details-1.jpg -------------------------------------------------------------------------------- /frontend/src/assets/img/portfolio/portfolio-details-2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ranizouaoui/ESP32-Based-IoT-Tracking-System/96c806979455f6fcaf8a6591b8451af4efc24e53/frontend/src/assets/img/portfolio/portfolio-details-2.jpg -------------------------------------------------------------------------------- /frontend/src/assets/img/portfolio/portfolio-details-3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ranizouaoui/ESP32-Based-IoT-Tracking-System/96c806979455f6fcaf8a6591b8451af4efc24e53/frontend/src/assets/img/portfolio/portfolio-details-3.jpg -------------------------------------------------------------------------------- /frontend/src/assets/img/skills.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ranizouaoui/ESP32-Based-IoT-Tracking-System/96c806979455f6fcaf8a6591b8451af4efc24e53/frontend/src/assets/img/skills.png -------------------------------------------------------------------------------- /frontend/src/assets/img/team/team-1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ranizouaoui/ESP32-Based-IoT-Tracking-System/96c806979455f6fcaf8a6591b8451af4efc24e53/frontend/src/assets/img/team/team-1.jpg -------------------------------------------------------------------------------- /frontend/src/assets/img/team/team-2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ranizouaoui/ESP32-Based-IoT-Tracking-System/96c806979455f6fcaf8a6591b8451af4efc24e53/frontend/src/assets/img/team/team-2.jpg -------------------------------------------------------------------------------- /frontend/src/assets/img/team/team-3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ranizouaoui/ESP32-Based-IoT-Tracking-System/96c806979455f6fcaf8a6591b8451af4efc24e53/frontend/src/assets/img/team/team-3.jpg -------------------------------------------------------------------------------- /frontend/src/assets/img/team/team-4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ranizouaoui/ESP32-Based-IoT-Tracking-System/96c806979455f6fcaf8a6591b8451af4efc24e53/frontend/src/assets/img/team/team-4.jpg -------------------------------------------------------------------------------- /frontend/src/assets/img/why-us.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ranizouaoui/ESP32-Based-IoT-Tracking-System/96c806979455f6fcaf8a6591b8451af4efc24e53/frontend/src/assets/img/why-us.png -------------------------------------------------------------------------------- /frontend/src/assets/imge.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ranizouaoui/ESP32-Based-IoT-Tracking-System/96c806979455f6fcaf8a6591b8451af4efc24e53/frontend/src/assets/imge.png -------------------------------------------------------------------------------- /frontend/src/assets/location.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ranizouaoui/ESP32-Based-IoT-Tracking-System/96c806979455f6fcaf8a6591b8451af4efc24e53/frontend/src/assets/location.png -------------------------------------------------------------------------------- /frontend/src/assets/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ranizouaoui/ESP32-Based-IoT-Tracking-System/96c806979455f6fcaf8a6591b8451af4efc24e53/frontend/src/assets/logo.png -------------------------------------------------------------------------------- /frontend/src/assets/med.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ranizouaoui/ESP32-Based-IoT-Tracking-System/96c806979455f6fcaf8a6591b8451af4efc24e53/frontend/src/assets/med.jpg -------------------------------------------------------------------------------- /frontend/src/assets/media.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ranizouaoui/ESP32-Based-IoT-Tracking-System/96c806979455f6fcaf8a6591b8451af4efc24e53/frontend/src/assets/media.jpg -------------------------------------------------------------------------------- /frontend/src/assets/message.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ranizouaoui/ESP32-Based-IoT-Tracking-System/96c806979455f6fcaf8a6591b8451af4efc24e53/frontend/src/assets/message.png -------------------------------------------------------------------------------- /frontend/src/assets/ouma.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ranizouaoui/ESP32-Based-IoT-Tracking-System/96c806979455f6fcaf8a6591b8451af4efc24e53/frontend/src/assets/ouma.png -------------------------------------------------------------------------------- /frontend/src/assets/phone.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ranizouaoui/ESP32-Based-IoT-Tracking-System/96c806979455f6fcaf8a6591b8451af4efc24e53/frontend/src/assets/phone.jpg -------------------------------------------------------------------------------- /frontend/src/assets/position.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ranizouaoui/ESP32-Based-IoT-Tracking-System/96c806979455f6fcaf8a6591b8451af4efc24e53/frontend/src/assets/position.png -------------------------------------------------------------------------------- /frontend/src/assets/trac.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ranizouaoui/ESP32-Based-IoT-Tracking-System/96c806979455f6fcaf8a6591b8451af4efc24e53/frontend/src/assets/trac.jpg -------------------------------------------------------------------------------- /frontend/src/assets/traceur.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ranizouaoui/ESP32-Based-IoT-Tracking-System/96c806979455f6fcaf8a6591b8451af4efc24e53/frontend/src/assets/traceur.png -------------------------------------------------------------------------------- /frontend/src/components/AboutView.vue: -------------------------------------------------------------------------------- 1 | 104 | -------------------------------------------------------------------------------- /frontend/src/components/Component3.vue: -------------------------------------------------------------------------------- 1 | 7 | -------------------------------------------------------------------------------- /frontend/src/components/ContactView.vue: -------------------------------------------------------------------------------- 1 | 78 | -------------------------------------------------------------------------------- /frontend/src/components/HomeView.vue: -------------------------------------------------------------------------------- 1 | 71 | 85 | 86 | 87 | -------------------------------------------------------------------------------- /frontend/src/components/LoginView.vue: -------------------------------------------------------------------------------- 1 | 54 | 84 | -------------------------------------------------------------------------------- /frontend/src/components/NavbarView.vue: -------------------------------------------------------------------------------- 1 | 29 | 46 | 47 | -------------------------------------------------------------------------------- /frontend/src/components/PricingView.vue: -------------------------------------------------------------------------------- 1 | 59 | -------------------------------------------------------------------------------- /frontend/src/components/ServicesView.vue: -------------------------------------------------------------------------------- 1 | 54 | -------------------------------------------------------------------------------- /frontend/src/components/SideBarView.vue: -------------------------------------------------------------------------------- 1 | 49 | -------------------------------------------------------------------------------- /frontend/src/components/UserView.vue: -------------------------------------------------------------------------------- 1 | 17 | 57 | -------------------------------------------------------------------------------- /frontend/src/components/layout/user-history.vue: -------------------------------------------------------------------------------- 1 | 28 | -------------------------------------------------------------------------------- /frontend/src/components/layout/user-homeView.vue: -------------------------------------------------------------------------------- 1 | 103 | 161 | -------------------------------------------------------------------------------- /frontend/src/firebase.js: -------------------------------------------------------------------------------- 1 | // Import the functions you need from the SDKs you need 2 | import { initializeApp } from "firebase/app"; 3 | import { getFirestore } from "firebase/firestore"; 4 | // TODO: Add SDKs for Firebase products that you want to use 5 | // https://firebase.google.com/docs/web/setup#available-libraries 6 | 7 | // Your web app's Firebase configuration 8 | // For Firebase JS SDK v7.20.0 and later, measurementId is optional 9 | 10 | const firebaseConfig = { 11 | apiKey: "AIzaSyB9G1utWxdOjattwoSMlHeFq9lFg1Vc7fg", 12 | authDomain: "gps-tracker-fafb6.firebaseapp.com", 13 | databaseURL: "https://gps-tracker-fafb6-default-rtdb.europe-west1.firebasedatabase.app", 14 | projectId: "gps-tracker-fafb6", 15 | storageBucket: "gps-tracker-fafb6.appspot.com", 16 | messagingSenderId: "545087426286", 17 | appId: "1:545087426286:web:6bfef4e8761870c1742dff" 18 | }; 19 | 20 | // Initialize Firebase 21 | const app = initializeApp(firebaseConfig); 22 | // Initialize Cloud Firestore and get a reference to the service 23 | const db = getFirestore(app); 24 | export default db; -------------------------------------------------------------------------------- /frontend/src/main.js: -------------------------------------------------------------------------------- 1 | import { createApp } from 'vue' 2 | import App from './App.vue' 3 | import router from './routes'; 4 | // CSS 5 | import 'bootstrap/dist/css/bootstrap.css' 6 | import 'bootstrap-vue/dist/bootstrap-vue.css' 7 | import 'bootstrap/dist/js/bootstrap.min.js' 8 | import 'jquery/src/jquery.js' 9 | import 'bootstrap-icons/font/bootstrap-icons.css'; 10 | // // Import the CSS files 11 | // import 'aos/dist/aos.css'; 12 | import 'boxicons/css/boxicons.min.css'; 13 | import 'glightbox/dist/css/glightbox.min.css'; 14 | import 'remixicon/fonts/remixicon.css'; 15 | import 'swiper/swiper-bundle.min.css'; 16 | 17 | const app = createApp(App); 18 | app.use(router); 19 | app.mount('#app'); -------------------------------------------------------------------------------- /frontend/src/routes.js: -------------------------------------------------------------------------------- 1 | import { createRouter, createWebHistory } from 'vue-router'; 2 | const routes = [ 3 | { 4 | 5 | path: '/', 6 | name: 'home', 7 | component: () => import('./components/HomeView') 8 | }, 9 | { 10 | 11 | path: '/about', 12 | name: 'about', 13 | component: () => import('./components/AboutView') 14 | }, 15 | { 16 | 17 | path: '/login', 18 | name: 'login', 19 | component: () => import('./components/LoginView') 20 | }, 21 | { 22 | path: '/services', 23 | name: 'services', 24 | component: () => import('./components/ServicesView') 25 | }, 26 | 27 | { 28 | path: '/contact', 29 | name: 'contact', 30 | component: () => import('./components/ContactView') 31 | }, 32 | { 33 | path: '/pricing', 34 | name: 'pricing', 35 | component: () => import('./components/PricingView') 36 | }, 37 | { 38 | path: '/user', 39 | name: 'user', 40 | component: () => import('./components/UserView') 41 | } 42 | ]; 43 | 44 | const router = createRouter({ 45 | history: createWebHistory(), 46 | routes 47 | }); 48 | 49 | export default router; 50 | -------------------------------------------------------------------------------- /frontend/vue.config.js: -------------------------------------------------------------------------------- 1 | const { defineConfig } = require('@vue/cli-service') 2 | module.exports = defineConfig({ 3 | transpileDependencies: true 4 | }) 5 | -------------------------------------------------------------------------------- /pictures/configuration.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ranizouaoui/ESP32-Based-IoT-Tracking-System/96c806979455f6fcaf8a6591b8451af4efc24e53/pictures/configuration.png -------------------------------------------------------------------------------- /pictures/configuration1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ranizouaoui/ESP32-Based-IoT-Tracking-System/96c806979455f6fcaf8a6591b8451af4efc24e53/pictures/configuration1.png -------------------------------------------------------------------------------- /pictures/home-interface.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ranizouaoui/ESP32-Based-IoT-Tracking-System/96c806979455f6fcaf8a6591b8451af4efc24e53/pictures/home-interface.png -------------------------------------------------------------------------------- /pictures/login-interface.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ranizouaoui/ESP32-Based-IoT-Tracking-System/96c806979455f6fcaf8a6591b8451af4efc24e53/pictures/login-interface.png -------------------------------------------------------------------------------- /pictures/services-interface.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ranizouaoui/ESP32-Based-IoT-Tracking-System/96c806979455f6fcaf8a6591b8451af4efc24e53/pictures/services-interface.png -------------------------------------------------------------------------------- /pictures/synoptique.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ranizouaoui/ESP32-Based-IoT-Tracking-System/96c806979455f6fcaf8a6591b8451af4efc24e53/pictures/synoptique.png -------------------------------------------------------------------------------- /pictures/user-history.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ranizouaoui/ESP32-Based-IoT-Tracking-System/96c806979455f6fcaf8a6591b8451af4efc24e53/pictures/user-history.png -------------------------------------------------------------------------------- /pictures/user-interface.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ranizouaoui/ESP32-Based-IoT-Tracking-System/96c806979455f6fcaf8a6591b8451af4efc24e53/pictures/user-interface.png --------------------------------------------------------------------------------