#include <WiFi.h>
#include <PubSubClient.h>
#include <Keypad.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27, 16, 2);
const char* ssid = "Wokwi-GUEST";
const char* password = "";
const char* mqtt_server = "broker.hivemq.com";
WiFiClient espClient;
PubSubClient client(espClient);
// Keypad
const byte ROWS = 4, COLS = 4;
char keys[ROWS][COLS] = {
{'1','2','3','A'},
{'4','5','6','B'},
{'7','8','9','C'},
{'*','0','#','D'}
};
byte rowPins[ROWS] = {13,12,14,27};
byte colPins[COLS] = {26,25,33,32};
Keypad keypad = Keypad(makeKeymap(keys), rowPins, colPins, ROWS, COLS);
// Data
String inputDigits = "";
String voterID = "wjb";
int candidateID = -1;
bool validStep = false;
// MQTT callback
void callback(char* topic, byte* payload, unsigned int length) {
String msg = "";
for (int i = 0; i < length; i++) msg += (char)payload[i];
lcd.clear();
lcd.print(msg);
}
// reconnect
void reconnect() {
while (!client.connected()) {
if (client.connect("ClientESP32")) {
client.subscribe("vote/response");
} else delay(2000);
}
}
// send vote
void sendVote() {
String payload = "{\"voter_id\":\"" + voterID + "\",\"candidate_id\":" + String(candidateID) + "}";
client.publish("vote/request", payload.c_str());
}
// reset
void resetAll() {
inputDigits = "";
voterID = "wjb";
validStep = false;
lcd.clear();
lcd.print("Enter ID:");
lcd.setCursor(0,1);
lcd.print("wjb");
}
void setup() {
lcd.init();
lcd.backlight();
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) delay(500);
client.setServer(mqtt_server, 1883);
client.setCallback(callback);
resetAll();
}
void loop() {
if (!client.connected()) reconnect();
client.loop();
char key = keypad.getKey();
if (key) {
if (!validStep) {
if (key == '*') resetAll();
else if (key == '#') {
if (inputDigits.length() == 6) {
voterID = "wjb" + inputDigits;
validStep = true;
lcd.clear();
lcd.print("Select (1-5)");
} else {
lcd.clear();
lcd.print("Invalid ID");
delay(1500);
resetAll();
}
}
else if (isDigit(key) && inputDigits.length() < 6) {
inputDigits += key;
lcd.setCursor(0,1);
lcd.print("wjb" + inputDigits);
}
}
else {
if (key >= '1' && key <= '5') {
candidateID = key - '0';
lcd.clear();
lcd.print("Sending...");
delay(800);
sendVote();
delay(1500);
resetAll();
}
else if (key == '*') resetAll();
}
}
}