Registration of badges and receiving votes only of voting badges implemented.

This commit is contained in:
2025-11-08 17:11:02 +00:00
parent 2a18995886
commit 34346e715d
20 changed files with 36262 additions and 35759 deletions

View File

@@ -1,10 +1,9 @@
#include <Arduino.h>
#include "main.h"
#define START_SCREEN_WAIT 4 * 200 // First number is the time in seconds
const char *ssid = "";
const char *password = "";
const char *ssid = "CIA";
const char *password = "passespacarola";
// Touchscreen pinout
#define XPT2046_IRQ 36
@@ -17,7 +16,7 @@ int x, y, z;
#define SCREEN_HEIGHT 320
// MQTT settings
const char* mqtt_server_ip = "10.164.67.98";
const char* mqtt_server_ip = "10.139.95.154";
const int mqtt_port = 1883;
//const char* mqtt_user = "badge_device";
//const char* mqtt_password = "letmein";
@@ -25,6 +24,8 @@ PicoMQTT::Client mqtt_client(mqtt_server_ip);
PicoMQTT::Server mqtt_server;
// Global variables
size_t num_badges;
size_t curr_vote = 0;
int start_screen = 0;
int ibvs_mode = 0;
int ping_number = 0;
@@ -32,14 +33,18 @@ unsigned long last_publish_time = 0;
bool ibvs_mode_done = false;
bool screenNeedsUpdate = true;
bool configDone = false;
bool get_imageDone = true;
bool get_imageDone = false;
bool winnerDone = false;
bool vote_end = false;
bool wifi_connected = false;
char current_screen = 'A';
char winner = '0';
char Badge_ID[9];
String badges;
std::vector<String> register_badges;
String current;
String topic_test = "voting/ready";
String topic_winner = "voting/winner";
String message = "Testing da thing #";
LongText question = {"To be or not to be ?", 4, 40};
ShortText orgev = {" ATO", 4, 4};
@@ -50,7 +55,9 @@ ShortText item3 = {"Maybe", 4, 140};
ShortText item4 = {"Abstain", 4, 170};
ShortText item5 = {"Null", 4, 200};
//lv_image_dsc_t dynamic_image;
lv_image_dsc_t* dynamic_img_dsc = NULL;
//WebServer server(80); // For web image uploader
#define DRAW_BUF_SIZE (SCREEN_WIDTH * SCREEN_HEIGHT / 10 * (LV_COLOR_DEPTH / 8))
uint32_t draw_buf[DRAW_BUF_SIZE / 4];
@@ -66,10 +73,76 @@ void setup() {
}
Serial.println("SPIFFS Mounted Successfully");
String LVGL_Arduino = String("LVGL Library Version: ") + lv_version_major() + "." + lv_version_minor() + "." + lv_version_patch();
Serial.println(LVGL_Arduino);
// Start LVGL
lv_init();
// ----------- SPIFFS driver for LVGL -----------------------------------
// Register SPIFFS with LVGL
static lv_fs_drv_t fs_drv;
lv_fs_drv_init(&fs_drv);
fs_drv.letter = 'S';
fs_drv.open_cb = [](lv_fs_drv_t *drv, const char *path, lv_fs_mode_t mode) -> void* {
fs::File *file = new fs::File();
// Add leading slash if not present
String fullPath = path;
if (!fullPath.startsWith("/")) {
fullPath = "/" + fullPath;
}
Serial.print("Opening: ");
Serial.println(fullPath);
if (mode == LV_FS_MODE_RD) {
*file = SPIFFS.open(fullPath, FILE_READ);
} else {
*file = SPIFFS.open(fullPath, FILE_WRITE);
}
if (file->operator bool()) {
Serial.println("File opened successfully!");
return (void*)file;
} else {
Serial.println("File open failed!");
delete file;
return NULL;
}
};
fs_drv.close_cb = [](lv_fs_drv_t *drv, void *file_p) -> lv_fs_res_t {
fs::File *file = (fs::File*)file_p;
file->close();
delete file;
return LV_FS_RES_OK;
};
fs_drv.read_cb = [](lv_fs_drv_t *drv, void *file_p, void *buf, uint32_t btr, uint32_t *br) -> lv_fs_res_t {
fs::File *file = (fs::File*)file_p;
*br = file->read((uint8_t*)buf, btr);
return LV_FS_RES_OK;
};
fs_drv.seek_cb = [](lv_fs_drv_t *drv, void *file_p, uint32_t pos, lv_fs_whence_t whence) -> lv_fs_res_t {
fs::File *file = (fs::File*)file_p;
file->seek(pos);
return LV_FS_RES_OK;
};
fs_drv.tell_cb = [](lv_fs_drv_t *drv, void *file_p, uint32_t *pos_p) -> lv_fs_res_t {
fs::File *file = (fs::File*)file_p;
*pos_p = file->position();
return LV_FS_RES_OK;
};
lv_fs_drv_register(&fs_drv);
Serial.println("LVGL FS driver registered");
// -------------------------------------------------------------------------
// Register print function for debugging
lv_log_register_print_cb(log_print);
@@ -100,7 +173,10 @@ void setup() {
xTaskCreate(mqtt_manager, "Manage_mqtt", 8192, NULL, 1, NULL);
wifi_connected = connect_wifi();
// For web image uploader
/* server.on("/upload", HTTP_POST, []() {}, handleImageUpload);
server.begin();
Serial.println("Web server started"); */
}
void loop() {
@@ -113,10 +189,13 @@ void loop() {
configDone = true;
}
if (!get_imageDone) {
get_image();
/* if (!get_imageDone) {
server.handleClient();
get_imageDone = true;
}
*/
// server.handleClient(); // For web image uploader
get_image();
if (winner != '0' && !winnerDone) {
@@ -132,7 +211,7 @@ void loop() {
configDone = true;
}
/* if (millis() - last_publish_time >= 60000) {
/* 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);
@@ -140,11 +219,14 @@ void loop() {
} */
if (vote_end) {
message = "3";
mqtt_server.publish(topic_winner, message);
vote_end = false;
}
}
vTaskDelay(8000 / portTICK_PERIOD_MS);
// vTaskDelay(10 / portTICK_PERIOD_MS);
delay(10);
}
void serial_config() {
@@ -301,8 +383,34 @@ void mqtt_subs() {
});
}
if (ibvs_mode == IBVS_PROCESSOR) {
mqtt_server.subscribe("#", [](const char * topic, const char * payload) {
Serial.printf("Received message in topic '%s': %s\r\n", topic, payload);
mqtt_server.subscribe("voter#", [](const char * topic, const char * payload) {
Serial.printf("Received message in topic '%s': %s\r\n", topic, payload);
String curr_badge(topic);
curr_badge.replace("voter/", ""); // Remove all colons
curr_badge = curr_badge.substring(0, 8);
bool found = false;
for (const String& badge : register_badges) {
if (curr_badge == badge) { // exact match
found = true;
break;
}
}
if (found) {
Serial.println("Badge is authorised");
curr_vote++;
} else {
Serial.println("Badge NOT found");
// This needs to move to screen manager in new filtering for 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;
});
}
}
@@ -310,7 +418,7 @@ void mqtt_subs() {
void mqtt_send_result(char result) {
char topic[32];
sprintf(topic, "voting/%s", Badge_ID);
sprintf(topic, "voter/%s", Badge_ID);
mqtt_client.publish(topic, String(result).c_str());
Serial.printf("Published \'%c\' to topic : ", result);
Serial.println(topic);
@@ -426,6 +534,10 @@ void screen_manager(void *pvParameters) {
break;
case 'H':
loadScreen(SCREEN_ID_IBVS_PROCESSOR);
// lv_scr_load_anim(objects.vote_wait, LV_SCR_LOAD_ANIM_FADE_IN, 200, 0, false);
break;
case 'I':
loadScreen(SCREEN_ID_NOT_AUTHORIZED);
// lv_scr_load_anim(objects.vote_wait, LV_SCR_LOAD_ANIM_FADE_IN, 200, 0, false);
break;
}
@@ -441,11 +553,11 @@ void screen_manager(void *pvParameters) {
void mqtt_manager(void *pvParameters) {
while (1) {
if (ibvs_mode == IBVS_BADGE) {
if (!ibvs_mode_done){
if (!ibvs_mode_done) {
mqtt_client.begin();
mqtt_subs();
ibvs_mode_done = true;
Serial.println("mqtt_subs() done once in badge mode"); // Debug
Serial.println("mqtt_subs() done once in badge mode"); // Debug
}
mqtt_client.loop();
vTaskDelay(5 / portTICK_PERIOD_MS);
@@ -468,110 +580,165 @@ void mqtt_manager(void *pvParameters) {
void badge_registration() {
bool confirmed = false;
while (!confirmed) {
Serial.println("Input the badges ID for registration, comma separated :");
// Clear any existing input
while(Serial.available()) Serial.read();
// Wait for complete line with Enter
// String input = "";
while (true) {
if (Serial.available() > 0) {
char c = Serial.read();
if (c == '\n' || c == '\r') {
if (badges.length() > 0) {
break; // Got Enter with text
} else {
Serial.println("Input the badges ID for registration, comma separated :");
// Continue waiting for input
}
} else {
badges+= c; // Add character to string
}
}
delay(10);
}
// input.toCharArray(badges, sizeof(badges));
Serial.print("You entered: ");
Serial.println(badges);
Serial.println("Is this correct? (y/n)");
while (Serial.available() == 0) delay(10);
char response = Serial.read();
Serial.println('\n');
if (response == 'y' || response == 'Y') {
confirmed = true;
for (size_t i = 0; i < badges.length(); ++i) {
char c = badges[i];
if (c == ',') { // end of one badge
register_badges.push_back(current);
current = ""; // start next badge
} 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() {
Serial.println("DEBUG: get_image() called");
if (Serial.available() > 0) {
Serial.println("DEBUG: Data available!");
String command = Serial.readStringUntil('\n');
command.trim();
Serial.print("DEBUG: Command = '");
Serial.print(command);
Serial.println("'");
if (command.startsWith("UPLOAD_IMAGE:")) {
// Extract filename and size
int colonPos = command.indexOf(':', 13);
String filename = command.substring(13, colonPos);
int fileSize = command.substring(colonPos + 1).toInt();
Serial.println("Ready to receive image");
Serial.print("Filename: ");
Serial.println(filename);
Serial.print("Size: ");
Serial.println(fileSize);
Serial.print("Receiving ");
Serial.print(filename);
Serial.print(" (");
Serial.print(fileSize);
Serial.println(" bytes)");
// Read data as it arrives
Serial.println("DEBUG: Starting to receive data...");
fs::File file = SPIFFS.open("/" + filename, FILE_WRITE);
if (file) {
Serial.println("DEBUG: File opened");
byte buffer[128]; // Smaller buffer
int remaining = fileSize;
int bytesReceived = 0;
unsigned long startTime = millis();
while (remaining > 0 && (millis() - startTime < 30000)) {
int available = Serial.available();
if (available > 0) {
int toRead = min(remaining, min(128, available));
int actualRead = Serial.readBytes(buffer, toRead);
file.write(buffer, actualRead);
remaining -= actualRead;
bytesReceived += actualRead;
delay(1000);
// Print progress every 10KB
if (bytesReceived % 10000 < 128) {
Serial.print("Received: ");
Serial.print(bytesReceived);
Serial.print(" / ");
Serial.println(fileSize);
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");
}
}
yield(); // Feed watchdog
}
file.close();
Serial.print("DEBUG: File closed. Bytes received: ");
Serial.println(bytesReceived);
if (remaining == 0) {
Serial.println("Image uploaded successfully!");
String fullPath = "/" + filename;
Serial.println("DEBUG: Calling load_image...");
load_image(fullPath.c_str());
} else {
Serial.print("ERROR: Incomplete upload. Remaining: ");
Serial.println(remaining);
}
} else {
Serial.println("Failed to open file for writing");
}
}
}
}
bool load_image(const char* filename) {
fs::File file = SPIFFS.open(filename, FILE_READ);
if (!file) {
Serial.println("Failed to open image file");
Serial.println("Failed to open image");
return false;
}
size_t fileSize = file.size();
Serial.print("Image file size: ");
Serial.print("Loading raw image, size: ");
Serial.println(fileSize);
// Allocate memory for the image data
// Allocate memory for raw pixel data
uint8_t* imageData = (uint8_t*)malloc(fileSize);
if (!imageData) {
Serial.println("Failed to allocate memory for image");
Serial.println("Memory allocation failed");
file.close();
return false;
}
// Read the entire file into memory
// Read raw data
file.read(imageData, fileSize);
file.close();
// Set the image source to the loaded data
// LVGL will decode the BMP automatically
lv_image_set_src(objects.picture, imageData);
// Create LVGL image descriptor for raw ARGB8888
static lv_image_dsc_t img_dsc;
img_dsc.header.cf = LV_COLOR_FORMAT_ARGB8888;
img_dsc.header.w = 130;
img_dsc.header.h = 150;
img_dsc.header.stride = 130 * 4; // 4 bytes per pixel
img_dsc.data = imageData;
img_dsc.data_size = fileSize;
Serial.println("Image loaded successfully!");
lv_image_set_src(objects.picture, &img_dsc);
Serial.println("Image loaded!");
return true;
}
@@ -600,4 +767,5 @@ bool connect_wifi() {
mac.replace(":", ""); // Remove all colons
strcpy(Badge_ID, mac.substring(0, 8).c_str()); // Get first 8 characters, 4 bytes
return true;
}
}