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

Binary file not shown.

Binary file not shown.

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

Binary file not shown.

Binary file not shown.

View File

@@ -954,4 +954,9 @@
.pio/libdeps/esp32dev/PicoMQTT/src/PicoMQTT/autoid.h \
.pio/libdeps/esp32dev/PicoMQTT/src/PicoMQTT/utils.h \
.pio/libdeps/esp32dev/PicoMQTT/src/PicoMQTT/server.h \
/home/ricardo/.platformio/packages/framework-arduinoespressif32/libraries/WebServer/src/WebServer.h \
/home/ricardo/.platformio/packages/framework-arduinoespressif32/libraries/WebServer/src/HTTP_Method.h \
/home/ricardo/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/nghttp/port/include/http_parser.h \
/home/ricardo/.platformio/packages/framework-arduinoespressif32/libraries/WebServer/src/Uri.h \
/home/ricardo/.platformio/packages/framework-arduinoespressif32/libraries/WebServer/src/detail/RequestHandler.h \
.pio/libdeps/esp32dev/ui/vars.h

View File

@@ -952,4 +952,9 @@
.pio/libdeps/esp32dev/PicoMQTT/src/PicoMQTT/autoid.h \
.pio/libdeps/esp32dev/PicoMQTT/src/PicoMQTT/utils.h \
.pio/libdeps/esp32dev/PicoMQTT/src/PicoMQTT/server.h \
/home/ricardo/.platformio/packages/framework-arduinoespressif32/libraries/WebServer/src/WebServer.h \
/home/ricardo/.platformio/packages/framework-arduinoespressif32/libraries/WebServer/src/HTTP_Method.h \
/home/ricardo/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/nghttp/port/include/http_parser.h \
/home/ricardo/.platformio/packages/framework-arduinoespressif32/libraries/WebServer/src/Uri.h \
/home/ricardo/.platformio/packages/framework-arduinoespressif32/libraries/WebServer/src/detail/RequestHandler.h \
.pio/libdeps/esp32dev/ui/vars.h .pio/libdeps/esp32dev/ui/actions.h

Binary file not shown.

View File

@@ -952,4 +952,9 @@
.pio/libdeps/esp32dev/PicoMQTT/src/PicoMQTT/autoid.h \
.pio/libdeps/esp32dev/PicoMQTT/src/PicoMQTT/utils.h \
.pio/libdeps/esp32dev/PicoMQTT/src/PicoMQTT/server.h \
/home/ricardo/.platformio/packages/framework-arduinoespressif32/libraries/WebServer/src/WebServer.h \
/home/ricardo/.platformio/packages/framework-arduinoespressif32/libraries/WebServer/src/HTTP_Method.h \
/home/ricardo/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/nghttp/port/include/http_parser.h \
/home/ricardo/.platformio/packages/framework-arduinoespressif32/libraries/WebServer/src/Uri.h \
/home/ricardo/.platformio/packages/framework-arduinoespressif32/libraries/WebServer/src/detail/RequestHandler.h \
.pio/libdeps/esp32dev/ui/vars.h .pio/libdeps/esp32dev/ui/actions.h

Binary file not shown.

View File

@@ -620,7 +620,8 @@
/*File system interfaces for common APIs */
/*API for fopen, fread, etc*/
/*API for fopen, fread, etc */
#define LV_USE_FS_STDIO 0
#if LV_USE_FS_STDIO
#define LV_FS_STDIO_LETTER '\0' /*Set an upper cased letter on which the drive will accessible (e.g. 'A')*/

View File

@@ -676,6 +676,30 @@ void tick_screen_ibvs_processor() {
}
}
void create_screen_not_authorized() {
lv_obj_t *obj = lv_obj_create(0);
objects.not_authorized = obj;
lv_obj_set_pos(obj, 0, 0);
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_t *parent_obj = obj;
{
lv_obj_t *obj = lv_label_create(parent_obj);
lv_obj_set_pos(obj, 26, 97);
lv_obj_set_size(obj, 268, 47);
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_label_set_text(obj, "This Badge is no authorized in this voting session !!!");
}
}
tick_screen_not_authorized();
}
void tick_screen_not_authorized() {
}
typedef void (*tick_screen_func_t)();
@@ -688,6 +712,7 @@ tick_screen_func_t tick_screen_funcs[] = {
tick_screen_vote_results,
tick_screen_ibvs_mode,
tick_screen_ibvs_processor,
tick_screen_not_authorized,
};
void tick_screen(int screen_index) {
tick_screen_funcs[screen_index]();
@@ -709,4 +734,5 @@ void create_screens() {
create_screen_vote_results();
create_screen_ibvs_mode();
create_screen_ibvs_processor();
create_screen_not_authorized();
}

View File

@@ -16,6 +16,7 @@ typedef struct _objects_t {
lv_obj_t *vote_results;
lv_obj_t *ibvs_mode;
lv_obj_t *ibvs_processor;
lv_obj_t *not_authorized;
lv_obj_t *obj0;
lv_obj_t *obj1;
lv_obj_t *obj2;
@@ -50,6 +51,7 @@ enum ScreensEnum {
SCREEN_ID_VOTE_RESULTS = 6,
SCREEN_ID_IBVS_MODE = 7,
SCREEN_ID_IBVS_PROCESSOR = 8,
SCREEN_ID_NOT_AUTHORIZED = 9,
};
void create_screen_start();
@@ -75,6 +77,9 @@ void tick_screen_ibvs_mode();
void create_screen_ibvs_processor();
void tick_screen_ibvs_processor();
void create_screen_not_authorized();
void tick_screen_not_authorized();
void tick_screen_by_id(enum ScreensEnum screenId);
void tick_screen(int screen_index);

View File

@@ -2,6 +2,7 @@
#define MAIN_H
#include <Arduino.h>
#include <vector>
#include <lvgl.h>
#include <TFT_eSPI.h>
#include <XPT2046_Touchscreen.h>
@@ -10,11 +11,15 @@
#include <WiFi.h>
#include <PicoMQTT.h>
#include <SPIFFS.h>
#include <WebServer.h>
#include "vars.h"
#include "actions.h"
#define IBVS_BADGE 1
#define IBVS_PROCESSOR 2
#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
// Struct objects for main data

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;
}
}