├── assets └── images │ ├── appwrite.png │ ├── mongodb.png │ └── CSMS_coloured.png ├── README.md ├── esp32.ino └── esp32cam.ino /assets/images/appwrite.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xditya/csms-hardware/main/assets/images/appwrite.png -------------------------------------------------------------------------------- /assets/images/mongodb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xditya/csms-hardware/main/assets/images/mongodb.png -------------------------------------------------------------------------------- /assets/images/CSMS_coloured.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xditya/csms-hardware/main/assets/images/CSMS_coloured.png -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Campus Services Management System - ESP32 Components 2 | 3 | This repository contains the ESP32 components for the Campus Services Management System project. These components handle the IoT functionality of the system. 4 | 5 | ## Files 6 | 7 | - `esp32.ino` - Contains the code for the main ESP32 microcontroller that handles sensor data and communication with the server 8 | - `esp32cam.ino` - Contains the code for the ESP32-CAM module that handles image capture and processing 9 | 10 | ## Main Project 11 | 12 | This is a component of the larger Campus Services Management System project. For the complete project, please visit: 13 | [Campus Services Management System](https://github.com/xditya/CampusServicesManagementSystem) 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
CSMSAppwriteMongoDB
23 |
-------------------------------------------------------------------------------- /esp32.ino: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | WiFiClient client; 5 | 6 | #include 7 | #include 8 | 9 | LCD_I2C lcd(0x27,20,4); 10 | 11 | 12 | float val,d=6000; 13 | int digits[8]; 14 | 15 | void setup() 16 | { 17 | Serial.begin(9600); 18 | WiFi.mode(WIFI_STA); 19 | WiFi.begin("iot","123456789"); 20 | Serial.println("connecting"); 21 | while(WiFi.status() != WL_CONNECTED) 22 | { 23 | Serial.print("."); 24 | delay(100); 25 | } 26 | 27 | ThingSpeak.begin(client); 28 | 29 | 30 | 31 | lcd.begin(); // initialize the lcd 32 | //lcd.init(); 33 | // Print a message to the LCD. 34 | lcd.backlight(); 35 | lcd.clear(); 36 | lcd.setCursor(0,1); 37 | lcd.print(" SHOW "); 38 | lcd.setCursor(0,2); 39 | lcd.print(" QR "); 40 | delay(2000); 41 | 42 | pinMode(32,OUTPUT); 43 | pinMode(33,OUTPUT); 44 | pinMode(25,OUTPUT); 45 | pinMode(26,OUTPUT); 46 | pinMode(27,OUTPUT); 47 | pinMode(16,OUTPUT); 48 | pinMode(19,OUTPUT); 49 | pinMode(18,OUTPUT); 50 | 51 | digitalWrite(32,0); 52 | digitalWrite(33,0); 53 | digitalWrite(25,0); 54 | digitalWrite(26,0); 55 | digitalWrite(27,0); 56 | digitalWrite(16,0); 57 | digitalWrite(18,0); 58 | digitalWrite(19,0); 59 | 60 | 61 | } 62 | 63 | void loop() 64 | { 65 | val = ThingSpeak.readFloatField(2888489,1,"93YYKUSCH3YW7S18"); 66 | lcd.begin(); 67 | if(val>0) 68 | { 69 | lcd.clear(); 70 | lcd.setCursor(0,1); 71 | lcd.print(" ORDER RECEIVED..."); 72 | delay(2000); 73 | // lcd.clear(); 74 | // lcd.setCursor(0,1); 75 | // lcd.print(" ORDER RECEIVED..."); 76 | // delay(2000); 77 | 78 | String payload = String((int)val); // Convert float to integer and then to string 79 | 80 | // String payload = String((int)val); // Convert float to integer and then to string 81 | while (payload.length() < 8) { 82 | payload = "0" + payload; // Add leading zeros until length is 8 83 | } 84 | Serial.println("Received Data: " + payload); 85 | 86 | if (payload.length() == 8) { 87 | for (int i = 0; i < 8; i++) { 88 | digits[i] = payload[i] - '0'; // Convert char to integer 89 | Serial.print("Digit "); 90 | Serial.print(i + 1); 91 | Serial.print(": "); 92 | Serial.println(digits[i]); 93 | } 94 | 95 | if(digits[0]>0) 96 | { 97 | lcd.clear(); 98 | lcd.setCursor(0,1); 99 | lcd.print(" PAROTTA x"); 100 | lcd.print(digits[0]); 101 | delay(2000); 102 | 103 | digitalWrite(27,1); 104 | delay(digits[0]*d); 105 | digitalWrite(27,0); 106 | 107 | } 108 | 109 | if(digits[1]>0) 110 | { 111 | lcd.clear(); 112 | lcd.setCursor(0,1); 113 | lcd.print(" BIRIYANI x"); 114 | lcd.print(digits[1]); 115 | delay(2000); 116 | 117 | digitalWrite(16,1); 118 | delay(digits[1]*d); 119 | digitalWrite(16,0); 120 | 121 | } 122 | 123 | if(digits[2]>0) 124 | { 125 | lcd.clear(); 126 | lcd.setCursor(0,1); 127 | lcd.print(" CHAPATTI x"); 128 | lcd.print(digits[2]); 129 | delay(2000); 130 | 131 | digitalWrite(26,1); 132 | delay(digits[2]*d); 133 | digitalWrite(26,0); 134 | 135 | } 136 | 137 | if(digits[3]>0) 138 | { 139 | lcd.clear(); 140 | lcd.setCursor(0,1); 141 | lcd.print(" CHICKEN CURRY x"); 142 | lcd.print(digits[3]); 143 | delay(2000); 144 | 145 | digitalWrite(25,1); 146 | delay(digits[3]*d); 147 | digitalWrite(25,0); 148 | 149 | } 150 | 151 | if(digits[4]>0) 152 | { 153 | lcd.clear(); 154 | lcd.setCursor(0,1); 155 | lcd.print(" BEEF CURRY x"); 156 | lcd.print(digits[4]); 157 | delay(2000); 158 | 159 | digitalWrite(32,1); 160 | delay(digits[4]*d); 161 | digitalWrite(32,0); 162 | 163 | } 164 | 165 | if(digits[5]>0) 166 | { 167 | lcd.clear(); 168 | lcd.setCursor(0,1); 169 | lcd.print(" FISH CURRY x"); 170 | lcd.print(digits[5]); 171 | delay(2000); 172 | 173 | digitalWrite(33,1); 174 | delay(digits[5]*d); 175 | digitalWrite(33,0); 176 | 177 | } 178 | 179 | if(digits[6]>0) 180 | { 181 | lcd.clear(); 182 | lcd.setCursor(0,1); 183 | lcd.print(" VEG CURRY x"); 184 | lcd.print(digits[6]); 185 | delay(2000); 186 | 187 | digitalWrite(18,1); 188 | delay(digits[6]*d); 189 | digitalWrite(18,0); 190 | 191 | } 192 | 193 | 194 | if(digits[7]>0) 195 | { 196 | lcd.clear(); 197 | lcd.setCursor(0,1); 198 | lcd.print(" MEALS x"); 199 | lcd.print(digits[7]); 200 | delay(2000); 201 | 202 | digitalWrite(19,1); 203 | delay(digits[7]*d); 204 | digitalWrite(19,0); 205 | 206 | } 207 | lcd.clear(); 208 | lcd.setCursor(0,1); 209 | lcd.print(" ORDER DELIVERED..."); 210 | delay(5000); 211 | lcd.clear(); 212 | lcd.setCursor(0,1); 213 | lcd.print(" THANK YOU...."); 214 | delay(5000); 215 | ThingSpeak.writeField(2888489,1,0,"Q6DL0DTT0H47UGAR"); 216 | 217 | } else { 218 | Serial.println("Error: Received data is not 8 digits long"); 219 | } 220 | 221 | 222 | } 223 | lcd.clear(); 224 | lcd.setCursor(0,1); 225 | lcd.print(" SHOW "); 226 | lcd.setCursor(0,2); 227 | lcd.print(" QR "); 228 | delay(2000); 229 | //delay(1000); 230 | } -------------------------------------------------------------------------------- /esp32cam.ino: -------------------------------------------------------------------------------- 1 | #include "esp_camera.h" 2 | #include "soc/soc.h" 3 | #include "soc/rtc_cntl_reg.h" 4 | #include "quirc.h" 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | // LED Control Pins 12 | #define LED_BUILTIN 4 13 | #define LED_DETECT 12 14 | #define LED_SUCCESS 13 15 | #define LED_COMPLETE 14 16 | 17 | // ThingSpeak Configuration 18 | const char *thingspeakAPIKey = "Q6DL0DTT0H47UGAR"; 19 | const char *thingspeakURL = "https://api.thingspeak.com/update"; 20 | 21 | // Network Configuration 22 | const char *ssid = "iot"; 23 | const char *password = "123456789"; 24 | const int WIFI_RETRIES = 5; 25 | const int HTTP_TIMEOUT = 15000; 26 | 27 | TaskHandle_t QRCodeReader_Task; 28 | #define CAMERA_MODEL_AI_THINKER 29 | 30 | #if defined(CAMERA_MODEL_AI_THINKER) 31 | // Camera pin definitions 32 | #define PWDN_GPIO_NUM 32 33 | #define RESET_GPIO_NUM -1 34 | #define XCLK_GPIO_NUM 0 35 | #define SIOD_GPIO_NUM 26 36 | #define SIOC_GPIO_NUM 27 37 | #define Y9_GPIO_NUM 35 38 | #define Y8_GPIO_NUM 34 39 | #define Y7_GPIO_NUM 39 40 | #define Y6_GPIO_NUM 36 41 | #define Y5_GPIO_NUM 21 42 | #define Y4_GPIO_NUM 19 43 | #define Y3_GPIO_NUM 18 44 | #define Y2_GPIO_NUM 5 45 | #define VSYNC_GPIO_NUM 25 46 | #define HREF_GPIO_NUM 23 47 | #define PCLK_GPIO_NUM 22 48 | #else 49 | #error "Camera model not selected" 50 | #endif 51 | 52 | struct quirc *q = NULL; 53 | 54 | void setup() 55 | { 56 | WRITE_PERI_REG(RTC_CNTL_BROWN_OUT_REG, 0); 57 | Serial.begin(115200); 58 | Serial.setDebugOutput(true); 59 | 60 | // Initialize LED pins 61 | pinMode(LED_BUILTIN, OUTPUT); 62 | pinMode(LED_DETECT, OUTPUT); 63 | pinMode(LED_SUCCESS, OUTPUT); 64 | pinMode(LED_COMPLETE, OUTPUT); 65 | digitalWrite(LED_BUILTIN, LOW); 66 | digitalWrite(LED_DETECT, LOW); 67 | digitalWrite(LED_SUCCESS, LOW); 68 | digitalWrite(LED_COMPLETE, LOW); 69 | 70 | // Initialize quirc decoder 71 | q = quirc_new(); 72 | if (!q) 73 | { 74 | Serial.println("Failed to create quirc object"); 75 | ESP.restart(); 76 | } 77 | 78 | // Connect to Wi-Fi with enhanced stability 79 | WiFi.setSleep(false); 80 | WiFi.setTxPower(WIFI_POWER_19_5dBm); 81 | connectToWiFi(); 82 | 83 | // Camera configuration 84 | configureCamera(); 85 | 86 | xTaskCreatePinnedToCore( 87 | QRCodeReader, 88 | "QRCodeReader_Task", 89 | 20000, 90 | NULL, 91 | 1, 92 | &QRCodeReader_Task, 93 | 0); 94 | } 95 | 96 | void loop() 97 | { 98 | delay(1); 99 | } 100 | 101 | void connectToWiFi() 102 | { 103 | Serial.println("\nConnecting to Wi-Fi"); 104 | WiFi.begin(ssid, password); 105 | 106 | int retries = 0; 107 | while (WiFi.status() != WL_CONNECTED && retries < WIFI_RETRIES) 108 | { 109 | digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN)); 110 | delay(500); 111 | Serial.print("."); 112 | retries++; 113 | } 114 | 115 | if (WiFi.status() != WL_CONNECTED) 116 | { 117 | Serial.println("\nWiFi connection failed"); 118 | ESP.restart(); 119 | } 120 | 121 | Serial.println("\nConnected! IP address: "); 122 | Serial.println(WiFi.localIP()); 123 | 124 | // Blink built-in LED 3 times 125 | for (int i = 0; i < 3; i++) 126 | { 127 | digitalWrite(LED_BUILTIN, HIGH); 128 | delay(100); 129 | digitalWrite(LED_BUILTIN, LOW); 130 | delay(100); 131 | } 132 | } 133 | 134 | void configureCamera() 135 | { 136 | camera_config_t config; 137 | config.ledc_channel = LEDC_CHANNEL_0; 138 | config.ledc_timer = LEDC_TIMER_0; 139 | config.pin_d0 = Y2_GPIO_NUM; 140 | config.pin_d1 = Y3_GPIO_NUM; 141 | config.pin_d2 = Y4_GPIO_NUM; 142 | config.pin_d3 = Y5_GPIO_NUM; 143 | config.pin_d4 = Y6_GPIO_NUM; 144 | config.pin_d5 = Y7_GPIO_NUM; 145 | config.pin_d6 = Y8_GPIO_NUM; 146 | config.pin_d7 = Y9_GPIO_NUM; 147 | config.pin_xclk = XCLK_GPIO_NUM; 148 | config.pin_pclk = PCLK_GPIO_NUM; 149 | config.pin_vsync = VSYNC_GPIO_NUM; 150 | config.pin_href = HREF_GPIO_NUM; 151 | config.pin_sscb_sda = SIOD_GPIO_NUM; 152 | config.pin_sscb_scl = SIOC_GPIO_NUM; 153 | config.pin_pwdn = PWDN_GPIO_NUM; 154 | config.pin_reset = RESET_GPIO_NUM; 155 | config.xclk_freq_hz = 20000000; 156 | config.pixel_format = PIXFORMAT_GRAYSCALE; 157 | config.frame_size = FRAMESIZE_QVGA; 158 | config.jpeg_quality = 7; 159 | config.fb_count = 1; 160 | 161 | esp_err_t err = esp_camera_init(&config); 162 | if (err != ESP_OK) 163 | { 164 | Serial.printf("Camera init failed: 0x%x", err); 165 | ESP.restart(); 166 | } 167 | 168 | sensor_t *s = esp_camera_sensor_get(); 169 | s->set_framesize(s, FRAMESIZE_QVGA); 170 | } 171 | 172 | void QRCodeReader(void *pvParameters) 173 | { 174 | Serial.println("\nQR Code Reader Task Started"); 175 | 176 | while (1) 177 | { 178 | camera_fb_t *fb = esp_camera_fb_get(); 179 | if (!fb) 180 | { 181 | Serial.println("Camera capture failed"); 182 | vTaskDelay(100 / portTICK_PERIOD_MS); 183 | continue; 184 | } 185 | 186 | // Validate frame buffer 187 | size_t expected_size = fb->width * fb->height; 188 | if (fb->len != expected_size) 189 | { 190 | Serial.printf("Invalid frame buffer: Expected %zu, got %zu\n", expected_size, fb->len); 191 | esp_camera_fb_return(fb); 192 | vTaskDelay(100 / portTICK_PERIOD_MS); 193 | continue; 194 | } 195 | 196 | quirc_resize(q, fb->width, fb->height); 197 | uint8_t *image = quirc_begin(q, NULL, NULL); 198 | if (image) 199 | { 200 | memcpy(image, fb->buf, fb->len); 201 | quirc_end(q); 202 | 203 | int count = quirc_count(q); 204 | if (count > 0) 205 | { 206 | digitalWrite(LED_DETECT, HIGH); 207 | struct quirc_code code; 208 | struct quirc_data data; 209 | quirc_extract(q, 0, &code); 210 | 211 | if (!quirc_decode(&code, &data)) 212 | { 213 | processQRCode((const char *)data.payload); 214 | } 215 | digitalWrite(LED_DETECT, LOW); 216 | } 217 | } 218 | 219 | esp_camera_fb_return(fb); 220 | vTaskDelay(50 / portTICK_PERIOD_MS); 221 | } 222 | } 223 | 224 | void processQRCode(const char *payload) 225 | { 226 | Serial.printf("\nDecoded Payload: %s\n", payload); 227 | 228 | // Split email and hash 229 | String qrData(payload); 230 | int underscoreIndex = qrData.indexOf('_'); 231 | if (underscoreIndex == -1) 232 | { 233 | Serial.println("Invalid QR Code format"); 234 | return; 235 | } 236 | 237 | String email = qrData.substring(0, underscoreIndex); 238 | String hash = qrData.substring(underscoreIndex + 1); 239 | String orderURL = "https://csms-api.deno.dev/order?email=" + email + "&hash=" + hash; 240 | Serial.println("Generated Order URL: " + orderURL); 241 | 242 | HTTPClient http; 243 | http.begin(orderURL); 244 | http.setTimeout(HTTP_TIMEOUT); 245 | 246 | int httpCode = http.GET(); 247 | if (httpCode == HTTP_CODE_OK) 248 | { 249 | processAPIResponse(http.getString(), email, hash); 250 | } 251 | else 252 | { 253 | Serial.printf("Order API Error: %d - %s\n", httpCode, http.errorToString(httpCode).c_str()); 254 | } 255 | http.end(); 256 | } 257 | 258 | void processAPIResponse(String response, String email, String hash) 259 | { 260 | Serial.println("API Response: " + response); 261 | 262 | DynamicJsonDocument doc(1024); 263 | deserializeJson(doc, response); 264 | const char *error = doc["error"]; 265 | 266 | Serial.print("Error Status: "); 267 | Serial.println(error ? error : "null"); 268 | 269 | if (!error) 270 | { 271 | handleValidOrder(doc, email, hash); 272 | } 273 | else if (strcmp(error, "Order deliverd!") == 0) 274 | { 275 | handleCompleteOrder(); 276 | } 277 | } 278 | 279 | void handleValidOrder(DynamicJsonDocument &doc, String &email, String &hash) 280 | { 281 | // Process items 282 | String itemString = "00000000"; 283 | if (doc.containsKey("items")) 284 | { 285 | JsonObject items = doc["items"]; 286 | for (JsonPair kv : items) 287 | { 288 | int itemCode = atoi(kv.key().c_str()); 289 | int count = kv.value().as(); 290 | 291 | if (itemCode >= 1 && itemCode <= 8) 292 | { 293 | itemString[itemCode - 1] = (count > 9) ? '9' : (count + '0'); 294 | } 295 | } 296 | } 297 | Serial.print("Item Codes: "); 298 | Serial.println(itemString); 299 | 300 | // Upload to ThingSpeak 301 | if (uploadToThingSpeak(itemString)) 302 | { 303 | Serial.println("ThingSpeak update successful"); 304 | } 305 | 306 | // Send completion URL 307 | if (sendCompletionRequest(email, hash)) 308 | { 309 | Serial.println("Completion URL notified"); 310 | } 311 | 312 | // Activate success LED 313 | digitalWrite(LED_SUCCESS, HIGH); 314 | delay(5000); 315 | digitalWrite(LED_SUCCESS, LOW); 316 | } 317 | 318 | void handleCompleteOrder() 319 | { 320 | digitalWrite(LED_COMPLETE, HIGH); 321 | delay(5000); 322 | digitalWrite(LED_COMPLETE, LOW); 323 | } 324 | 325 | bool uploadToThingSpeak(String &itemString) 326 | { 327 | HTTPClient httpTS; 328 | String tsURL = String(thingspeakURL) + "?api_key=" + thingspeakAPIKey + "&field1=" + itemString; 329 | 330 | httpTS.begin(tsURL); 331 | httpTS.setTimeout(HTTP_TIMEOUT); 332 | 333 | int tsCode = httpTS.GET(); 334 | bool success = (tsCode == HTTP_CODE_OK); 335 | 336 | if (!success) 337 | { 338 | Serial.printf("ThingSpeak Error: %d - %s\n", tsCode, httpTS.errorToString(tsCode).c_str()); 339 | } 340 | 341 | httpTS.end(); 342 | return success; 343 | } 344 | 345 | bool sendCompletionRequest(String &email, String &hash) 346 | { 347 | String completionURL = "https://csms-api.deno.dev/order/complete?email=" + email + "&hash=" + hash; 348 | Serial.println("Attempting Completion URL: " + completionURL); 349 | 350 | WiFiClientSecure client; 351 | HTTPClient httpComplete; 352 | client.setInsecure(); 353 | client.setTimeout(HTTP_TIMEOUT); 354 | 355 | bool success = false; 356 | int retries = 3; 357 | 358 | while (retries-- > 0 && !success) 359 | { 360 | if (httpComplete.begin(client, completionURL)) 361 | { 362 | httpComplete.setTimeout(HTTP_TIMEOUT); 363 | int code = httpComplete.GET(); 364 | 365 | if (code == HTTP_CODE_OK) 366 | { 367 | success = true; 368 | } 369 | else 370 | { 371 | Serial.printf("Completion Error (Attempt %d): %d - %s\n", 372 | 3 - retries, code, httpComplete.errorToString(code).c_str()); 373 | } 374 | httpComplete.end(); 375 | } 376 | client.stop(); 377 | delay(1000); 378 | } 379 | 380 | return success; 381 | } --------------------------------------------------------------------------------