Upload files now through http, working fast and good. Implemented new network with dedicated router and fixed IP for processor.

This commit is contained in:
2025-11-09 21:26:16 +00:00
parent 34346e715d
commit dbcb8c50f7
12 changed files with 41975 additions and 40112 deletions

Binary file not shown.

Binary file not shown.

File diff suppressed because one or more lines are too long

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -618,7 +618,7 @@ void create_screen_ibvs_processor() {
lv_obj_t *parent_obj = obj; lv_obj_t *parent_obj = obj;
{ {
lv_obj_t *obj = lv_spinner_create(parent_obj); lv_obj_t *obj = lv_spinner_create(parent_obj);
lv_obj_set_pos(obj, 211, 120); lv_obj_set_pos(obj, 232, 100);
lv_obj_set_size(obj, 80, 80); lv_obj_set_size(obj, 80, 80);
lv_spinner_set_anim_params(obj, 1000, 60); lv_spinner_set_anim_params(obj, 1000, 60);
} }
@@ -638,7 +638,7 @@ void create_screen_ibvs_processor() {
lv_obj_t *obj = lv_textarea_create(parent_obj); lv_obj_t *obj = lv_textarea_create(parent_obj);
objects.obj11 = obj; objects.obj11 = obj;
lv_obj_set_pos(obj, 10, 180); lv_obj_set_pos(obj, 10, 180);
lv_obj_set_size(obj, 180, 50); lv_obj_set_size(obj, 208, 50);
lv_textarea_set_max_length(obj, 128); lv_textarea_set_max_length(obj, 128);
lv_textarea_set_one_line(obj, false); lv_textarea_set_one_line(obj, false);
lv_textarea_set_password_mode(obj, false); lv_textarea_set_password_mode(obj, false);
@@ -681,7 +681,7 @@ void create_screen_not_authorized() {
objects.not_authorized = obj; objects.not_authorized = obj;
lv_obj_set_pos(obj, 0, 0); lv_obj_set_pos(obj, 0, 0);
lv_obj_set_size(obj, 320, 240); lv_obj_set_size(obj, 320, 240);
lv_obj_set_style_bg_color(obj, lv_color_hex(0xff7e2929), LV_PART_MAIN | LV_STATE_DEFAULT); lv_obj_set_style_bg_color(obj, lv_color_hex(0xffff0000), LV_PART_MAIN | LV_STATE_DEFAULT);
{ {
lv_obj_t *parent_obj = obj; lv_obj_t *parent_obj = obj;
{ {
@@ -689,8 +689,8 @@ void create_screen_not_authorized() {
lv_obj_set_pos(obj, 26, 97); lv_obj_set_pos(obj, 26, 97);
lv_obj_set_size(obj, 268, 47); lv_obj_set_size(obj, 268, 47);
lv_label_set_long_mode(obj, LV_LABEL_LONG_SCROLL_CIRCULAR); lv_label_set_long_mode(obj, LV_LABEL_LONG_SCROLL_CIRCULAR);
lv_obj_set_style_text_font(obj, &lv_font_montserrat_24, LV_PART_MAIN | LV_STATE_DEFAULT); lv_obj_set_style_text_font(obj, &lv_font_montserrat_40, LV_PART_MAIN | LV_STATE_DEFAULT);
lv_label_set_text(obj, "This Badge is no authorized in this voting session !!!"); lv_label_set_text(obj, "This Badge is not authorized in this voting session !!!");
} }
} }

View File

@@ -21,6 +21,13 @@
#define START_SCREEN_WAIT (4 * 200) // First number is the time in seconds #define START_SCREEN_WAIT (4 * 200) // First number is the time in seconds
#define NUM_OF_BADGES (10 + (10*8)) // First and second number have to be equal and is the number of badges #define NUM_OF_BADGES (10 + (10*8)) // First and second number have to be equal and is the number of badges
// 0 = off
// 1 = level-1 (verbose) prints ONLY level-1 messages
// 2 = level-2 (normal) prints level-2 AND (because level-2 “contains” level-1) also level-1
#define DBG_LEVEL 1 // change at build-time
#define DBG_L1(fmt, ...) do { if (DBG_LEVEL >= 1) Serial.printf(fmt, ##__VA_ARGS__); } while (0)
#define DBG_L2(fmt, ...) do { if (DBG_LEVEL >= 2) Serial.printf(fmt, ##__VA_ARGS__); } while (0)
// Struct objects for main data // Struct objects for main data
struct ShortText { struct ShortText {
@@ -49,7 +56,9 @@ void log_print(lv_log_level_t level, const char * buf);
void touchscreen_read(lv_indev_t * indev, lv_indev_data_t * data); void touchscreen_read(lv_indev_t * indev, lv_indev_data_t * data);
void screen_manager(void *pvParameters); void screen_manager(void *pvParameters);
void mqtt_manager(void *pvParameters); void mqtt_manager(void *pvParameters);
void get_image();
bool load_image(const char* filename); bool load_image(const char* filename);
void listSPIFFS();
void handleImageUpload();
void handleUploadComplete();
#endif #endif

View File

@@ -2,8 +2,11 @@
#include "main.h" #include "main.h"
const char *ssid = "CIA"; const char *ssid = "IBVS_wuDa5d";
const char *password = "passespacarola"; const char *password = "Yai6maiph6oi";
IPAddress processor_IP(172, 20, 50, 35);
IPAddress gateway(172, 16, 0, 1);
IPAddress subnet(255, 240, 0, 0);
// Touchscreen pinout // Touchscreen pinout
#define XPT2046_IRQ 36 #define XPT2046_IRQ 36
@@ -16,7 +19,7 @@ int x, y, z;
#define SCREEN_HEIGHT 320 #define SCREEN_HEIGHT 320
// MQTT settings // MQTT settings
const char* mqtt_server_ip = "10.139.95.154"; const char* mqtt_server_ip = "172.20.50.35";
const int mqtt_port = 1883; const int mqtt_port = 1883;
//const char* mqtt_user = "badge_device"; //const char* mqtt_user = "badge_device";
//const char* mqtt_password = "letmein"; //const char* mqtt_password = "letmein";
@@ -57,7 +60,7 @@ ShortText item5 = {"Null", 4, 200};
lv_image_dsc_t* dynamic_img_dsc = NULL; lv_image_dsc_t* dynamic_img_dsc = NULL;
//WebServer server(80); // For web image uploader WebServer server(80); // For web image uploader
#define DRAW_BUF_SIZE (SCREEN_WIDTH * SCREEN_HEIGHT / 10 * (LV_COLOR_DEPTH / 8)) #define DRAW_BUF_SIZE (SCREEN_WIDTH * SCREEN_HEIGHT / 10 * (LV_COLOR_DEPTH / 8))
uint32_t draw_buf[DRAW_BUF_SIZE / 4]; uint32_t draw_buf[DRAW_BUF_SIZE / 4];
@@ -174,9 +177,9 @@ void setup() {
wifi_connected = connect_wifi(); wifi_connected = connect_wifi();
// For web image uploader // For web image uploader
/* server.on("/upload", HTTP_POST, []() {}, handleImageUpload); server.on("/upload", HTTP_POST, handleUploadComplete, handleImageUpload);
server.begin(); server.begin();
Serial.println("Web server started"); */ Serial.println("Web server started");
} }
void loop() { void loop() {
@@ -185,18 +188,15 @@ void loop() {
if (ibvs_mode == IBVS_BADGE) { if (ibvs_mode == IBVS_BADGE) {
if (!configDone) { if (!configDone) {
Serial.println("Entering badge mode..."); Serial.println("Entering badge mode...");
vTaskDelay(1000 / portTICK_PERIOD_MS);
serial_config(); serial_config();
vTaskDelay(1000 / portTICK_PERIOD_MS);
Serial.println("If you want to upload your picture type the following in a terminal:");
Serial.printf("curl -F \"file=@yourfile.bin\" http://%s/upload\r\n", WiFi.localIP().toString().c_str());
configDone = true; configDone = true;
} }
/* if (!get_imageDone) { server.handleClient(); // For web image uploader
server.handleClient();
get_imageDone = true;
}
*/
// server.handleClient(); // For web image uploader
get_image();
if (winner != '0' && !winnerDone) { if (winner != '0' && !winnerDone) {
Winner_Screen(); Winner_Screen();
@@ -207,26 +207,21 @@ void loop() {
if (ibvs_mode == IBVS_PROCESSOR) { if (ibvs_mode == IBVS_PROCESSOR) {
if (!configDone) { if (!configDone) {
Serial.println("Entering processor mode..."); Serial.println("Entering processor mode...");
WiFi.config(processor_IP, gateway, subnet);
set_var_ui_ip(WiFi.localIP().toString().c_str());
badge_registration(); badge_registration();
configDone = true; configDone = true;
} }
/* if (millis() - last_publish_time >= 60000) { // Debug
message = "MQTT server ping #" + String(ping_number++);
Serial.printf("Publishing message in topic '%s': %s\r\n", topic_test.c_str(), message.c_str());
mqtt_server.publish(topic_test, message);
last_publish_time = millis();
} */
if (vote_end) { if (vote_end) {
message = "3"; message = '3';
mqtt_server.publish(topic_winner, message); mqtt_server.publish(topic_winner, message);
vote_end = false; vote_end = false;
} }
} }
// vTaskDelay(10 / portTICK_PERIOD_MS); vTaskDelay(10 / portTICK_PERIOD_MS);
delay(10);
} }
void serial_config() { void serial_config() {
@@ -234,7 +229,6 @@ void serial_config() {
bool confirmed = false; bool confirmed = false;
while (!confirmed) { while (!confirmed) {
// Ask for name
Serial.println("Please enter your name:"); Serial.println("Please enter your name:");
// Clear any existing input // Clear any existing input
@@ -281,7 +275,6 @@ void serial_config() {
confirmed = false; confirmed = false;
while (!confirmed) { while (!confirmed) {
// Ask for name
Serial.println("Please enter the Organization or Event name:"); Serial.println("Please enter the Organization or Event name:");
// Clear any existing input // Clear any existing input
@@ -320,16 +313,16 @@ void serial_config() {
strcpy(orgev.text, buffer); strcpy(orgev.text, buffer);
set_var_ui_orgev(buffer); set_var_ui_orgev(buffer);
confirmed = true; confirmed = true;
Serial.println("Organization/Event name saved!"); Serial.println("Organization/Event name saved!\r\n");
} }
} }
Serial.print("Here is your ID: "); Serial.print("Here is your ID: ");
Serial.println(Badge_ID); Serial.println(Badge_ID);
Serial.println("Write it down."); Serial.println("Write it down.\r\n");
current_screen = 'C'; current_screen = 'C';
screenNeedsUpdate = true; screenNeedsUpdate = true;
Serial.printf("Current screen is: %c\r\n", current_screen); // Debug // DBG_L1("Current screen is: %c\r\n", current_screen); // Debug
} }
void mqtt_subs() { void mqtt_subs() {
@@ -372,8 +365,9 @@ void mqtt_subs() {
} }
else if (strcmp(topic, "voting/winner") == 0) { else if (strcmp(topic, "voting/winner") == 0) {
winner = payload[0]; winner = payload[0];
Serial.println("Im in the mqtt receive winner"); // Serial.println("Im in the mqtt receive winner");
} DBG_L1("Im in the mqtt receive winner");
}
else if (strcmp(topic, "voting/ready") == 0) { else if (strcmp(topic, "voting/ready") == 0) {
if (strcmp(payload, "start") == 0) { if (strcmp(payload, "start") == 0) {
current_screen = 'D'; current_screen = 'D';
@@ -381,13 +375,22 @@ void mqtt_subs() {
} }
} }
}); });
mqtt_client.subscribe("illegal", [](const char *topic, const char *payload) {
Serial.printf("Received message in topic '%s': %s\r\n", topic, payload);
if (strcmp(payload, Badge_ID) == 0) {
current_screen = 'I';
screenNeedsUpdate = true;
}
});
} }
if (ibvs_mode == IBVS_PROCESSOR) { if (ibvs_mode == IBVS_PROCESSOR) {
mqtt_server.subscribe("voter#", [](const char * topic, const char * payload) { mqtt_server.subscribe("voter#", [](const char * topic, const char * payload) {
Serial.printf("Received message in topic '%s': %s\r\n", topic, payload); Serial.printf("Received message in topic '%s': %s\r\n", topic, payload);
String curr_badge(topic); String curr_badge(topic);
curr_badge.replace("voter/", ""); // Remove all colons curr_badge.replace("voter/", "");
curr_badge = curr_badge.substring(0, 8); curr_badge = curr_badge.substring(0, 8);
bool found = false; bool found = false;
@@ -402,12 +405,8 @@ void mqtt_subs() {
Serial.println("Badge is authorised"); Serial.println("Badge is authorised");
curr_vote++; curr_vote++;
} else { } else {
Serial.println("Badge NOT found"); Serial.println("Badge NOT found");
// This needs to move to screen manager in new filtering for illegal/curr_badge mqtt_server.publish("illegal", curr_badge);
// and if curr_badge matches then the next 2 lines
// current_screen = 'I';
// screenNeedsUpdate = true;
// in here it has to publish server something like illegal/curr_badge
} }
if (curr_vote == num_badges) vote_end = true; if (curr_vote == num_badges) vote_end = true;
@@ -486,13 +485,13 @@ void screen_manager(void *pvParameters) {
while (1) { while (1) {
if (start_screen < START_SCREEN_WAIT) { // If not the wanted seconds keep counting if (start_screen < START_SCREEN_WAIT) { // If not the wanted seconds keep counting
start_screen++; start_screen++;
// Serial.printf("Counting: %d\r\n", start_screen); // Debug DBG_L2("Counting: %d\r\n", start_screen);
} }
else if (start_screen == START_SCREEN_WAIT && !wifi_connected) { else if (start_screen == START_SCREEN_WAIT && !wifi_connected) {
start_screen = START_SCREEN_WAIT - 600; // If wanted seconds but no wifi wait 1 second start_screen = START_SCREEN_WAIT - 600; // If wanted seconds but no wifi wait 1 second
} }
else if (start_screen == START_SCREEN_WAIT && wifi_connected) { else if (start_screen == START_SCREEN_WAIT && wifi_connected) {
Serial.println("Switching to screen G"); // Debug DBG_L1("Switching to screen G\r\n"); // Debug
current_screen = 'G'; current_screen = 'G';
screenNeedsUpdate = true; screenNeedsUpdate = true;
start_screen = START_SCREEN_WAIT+10; start_screen = START_SCREEN_WAIT+10;
@@ -500,7 +499,7 @@ void screen_manager(void *pvParameters) {
// Here we update the screen only if there is a change // Here we update the screen only if there is a change
if (screenNeedsUpdate) { if (screenNeedsUpdate) {
Serial.printf("Loading screen: %c\r\n", current_screen); // Debug DBG_L1("Loading screen: %c\r\n", current_screen); // Debug
switch (current_screen) { switch (current_screen) {
case 'A': case 'A':
loadScreen(SCREEN_ID_START); loadScreen(SCREEN_ID_START);
@@ -557,7 +556,7 @@ void mqtt_manager(void *pvParameters) {
mqtt_client.begin(); mqtt_client.begin();
mqtt_subs(); mqtt_subs();
ibvs_mode_done = true; ibvs_mode_done = true;
Serial.println("mqtt_subs() done once in badge mode"); // Debug DBG_L1("mqtt_subs() done once in badge mode"); // Debug
} }
mqtt_client.loop(); mqtt_client.loop();
vTaskDelay(5 / portTICK_PERIOD_MS); vTaskDelay(5 / portTICK_PERIOD_MS);
@@ -567,7 +566,7 @@ void mqtt_manager(void *pvParameters) {
mqtt_server.begin(); mqtt_server.begin();
mqtt_subs(); mqtt_subs();
ibvs_mode_done = true; ibvs_mode_done = true;
Serial.println("mqtt_subs() done once in processor mode"); // Debug DBG_L1("mqtt_subs() done once in processor mode"); // Debug
} }
mqtt_server.loop(); mqtt_server.loop();
vTaskDelay(5 / portTICK_PERIOD_MS); vTaskDelay(5 / portTICK_PERIOD_MS);
@@ -579,132 +578,63 @@ void mqtt_manager(void *pvParameters) {
} }
void badge_registration() { void badge_registration() {
bool confirmed = false; bool confirmed = false;
while (!confirmed) {
badges = ""; // 2. start fresh
current = "";
while (!confirmed) { Serial.println("Input the badges ID for comma-separated :");
Serial.println("Input the badges ID for registration, comma separated :"); while (Serial.available()) Serial.read(); // flush
// Clear any existing input // read full line
while(Serial.available()) Serial.read(); for (;;) {
if (Serial.available()) {
// Wait for complete line with Enter
// String input = "";
while (true) {
if (Serial.available() > 0) {
char c = Serial.read(); char c = Serial.read();
if (c == '\n' || c == '\r') { if (c == '\n' || c == '\r') {
if (badges.length() > 0) { if (badges.length()) break;
break; // Got Enter with text Serial.println("Empty input, please Input the badges ID for comma-separated :");
} else { } else badges += c;
Serial.println("Input the badges ID for registration, comma separated :");
// Continue waiting for input
}
} else {
badges+= c; // Add character to string
}
} }
delay(10); delay(10);
} }
// input.toCharArray(badges, sizeof(badges)); Serial.print("You entered: "); Serial.println(badges);
Serial.println("Correct? (y/n)");
while (!Serial.available()) delay(10);
Serial.print("You entered: "); char resp = Serial.read(); // get single char
Serial.println(badges); // 3. discard the rest of the line
Serial.println("Is this correct? (y/n)"); while (Serial.available()) Serial.read();
while (Serial.available() == 0) delay(10); if (resp == 'y' || resp == 'Y') {
char response = Serial.read();
Serial.println('\n');
if (response == 'y' || response == 'Y') {
confirmed = true; confirmed = true;
for (size_t i = 0; i < badges.length(); ++i) { // split
char c = badges[i]; for (size_t i = 0; i < badges.length(); ++i) {
if (c == ',') { // end of one badge char c = badges[i];
register_badges.push_back(current); if (c == ',') {
current = ""; // start next badge register_badges.push_back(current);
} else { current = "";
current += c; } else current += c;
}
}
if (current.length()) register_badges.push_back(current); // last badge (no trailing comma)
num_badges = register_badges.size();
Serial.printf("%d badges were registered for voting :\r\n", (int)num_badges);
for (const String& each_b: register_badges) {
Serial.println(each_b);
}
}
}
}
void get_image() {
if (Serial.available() > 0) {
String command = Serial.readStringUntil('\n');
command.trim();
if (command.startsWith("UPLOAD_IMAGE:")) {
int colonPos = command.indexOf(':', 13);
String filename = command.substring(13, colonPos);
int fileSize = command.substring(colonPos + 1).toInt();
Serial.print("Receiving ");
Serial.print(filename);
Serial.print(" (");
Serial.print(fileSize);
Serial.println(" bytes)");
delay(1000);
fs::File file = SPIFFS.open("/" + filename, FILE_WRITE);
if (file) {
int totalRead = 0;
byte buffer[512]; // Larger buffer
unsigned long lastRead = millis();
while (totalRead < fileSize && (millis() - lastRead < 60000)) { // 60 second timeout
int available = Serial.available();
if (available > 0) {
int toRead = min(512, min(fileSize - totalRead, available));
Serial.readBytes(buffer, toRead); // Use readBytes instead of manual read
file.write(buffer, toRead);
totalRead += toRead;
lastRead = millis();
// Progress indicator
if (totalRead % 20000 == 0) {
Serial.print(totalRead);
Serial.print("/");
Serial.println(fileSize);
}
}
yield();
}
file.close();
Serial.print("Total received: ");
Serial.println(totalRead);
if (totalRead == fileSize) {
Serial.println("Upload complete!");
String fullPath = "/" + filename;
load_image(fullPath.c_str());
} else {
Serial.print("Upload failed - missing ");
Serial.print(fileSize - totalRead);
Serial.println(" bytes");
}
} else {
Serial.println("File open failed");
} }
if (current.length()) register_badges.push_back(current);
num_badges = register_badges.size();
Serial.printf("\r\n%u badges registered\r\n", num_badges);
for (const String& b : register_badges) Serial.println(b);
} }
} }
} }
bool load_image(const char* filename) { bool load_image(const char* filename) {
// FREE OLD IMAGE FIRST - CRITICAL!
static uint8_t* previousImageData = NULL;
if (previousImageData != NULL) {
free(previousImageData);
previousImageData = NULL;
Serial.println("Freed previous image memory");
}
fs::File file = SPIFFS.open(filename, FILE_READ); fs::File file = SPIFFS.open(filename, FILE_READ);
if (!file) { if (!file) {
Serial.println("Failed to open image"); Serial.println("Failed to open image");
@@ -732,12 +662,14 @@ bool load_image(const char* filename) {
img_dsc.header.cf = LV_COLOR_FORMAT_ARGB8888; img_dsc.header.cf = LV_COLOR_FORMAT_ARGB8888;
img_dsc.header.w = 130; img_dsc.header.w = 130;
img_dsc.header.h = 150; img_dsc.header.h = 150;
img_dsc.header.stride = 130 * 4; // 4 bytes per pixel img_dsc.header.stride = 130 * 4;
img_dsc.data = imageData; img_dsc.data = imageData;
img_dsc.data_size = fileSize; img_dsc.data_size = fileSize;
lv_image_set_src(objects.picture, &img_dsc); lv_image_set_src(objects.picture, &img_dsc);
previousImageData = imageData; // Save for next time
Serial.println("Image loaded!"); Serial.println("Image loaded!");
return true; return true;
} }
@@ -769,3 +701,72 @@ bool connect_wifi() {
return true; return true;
} }
void listSPIFFS() {
Serial.println("Files in SPIFFS:");
fs::File root = SPIFFS.open("/");
fs::File file = root.openNextFile();
while(file) {
Serial.print(" ");
Serial.print(file.name());
Serial.print(" - ");
Serial.print(file.size());
Serial.println(" bytes");
file = root.openNextFile();
}
}
void handleImageUpload() {
HTTPUpload& upload = server.upload();
static fs::File uploadFile;
if (upload.status == UPLOAD_FILE_START) {
// Delete ALL files in SPIFFS before new upload
Serial.println("Cleaning SPIFFS...");
fs::File root = SPIFFS.open("/");
fs::File file = root.openNextFile();
while(file) {
if (!file.isDirectory()) { // ADD THIS CHECK
String name = String(file.name());
file.close();
SPIFFS.remove(name);
Serial.print("Deleted: ");
Serial.println(name);
file = root.openNextFile();
} else {
file.close();
file = root.openNextFile();
}
}
Serial.println("SPIFFS cleaned");
String filename = "/" + upload.filename;
Serial.print("Upload start: ");
Serial.println(filename);
uploadFile = SPIFFS.open(filename, FILE_WRITE);
if (!uploadFile) {
Serial.println("Failed to open file!");
}
}
else if (upload.status == UPLOAD_FILE_WRITE) {
if (uploadFile) {
uploadFile.write(upload.buf, upload.currentSize);
}
}
else if (upload.status == UPLOAD_FILE_END) {
if (uploadFile) {
uploadFile.close();
Serial.print("Upload complete: ");
Serial.println(upload.totalSize);
}
}
}
void handleUploadComplete() {
HTTPUpload& upload = server.upload();
String filename = "/" + upload.filename;
Serial.print("Loading image: ");
Serial.println(filename);
load_image(filename.c_str());
server.send(200, "text/plain", "Upload OK");
}