Registration of badges and receiving votes only of voting badges implemented.
This commit is contained in:
336
src/main.cpp
336
src/main.cpp
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user