#include <WiFi.h>
#include <HTTPClient.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <LiquidCrystal_I2C.h>
#include <Keypad.h>
#include <Preferences.h>
// OLED Display
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire);
// LCD Display (I2C)
LiquidCrystal_I2C lcd(0x27, 16, 2);
// Keypad setup
const byte ROWS = 4, COLS = 3;
char keys[ROWS][COLS] = {
{'1','2','3'},
{'4','5','6'},
{'7','8','9'},
{'*','0','#'}
};
byte rowPins[ROWS] = {4, 5, 18, 19};
byte colPins[COLS] = {23, 25, 2};
Keypad keypad = Keypad(makeKeymap(keys), rowPins, colPins, ROWS, COLS);
String keypadBuffer = "";
// WiFi credentials
const char* ssid = "Wokwi-GUEST";
const char* password = "";
// ThingsBoard server & token
const char* tbServer = "http://thingsboard.cloud";
const char* tbToken = "wofqkaayfjmgcg8hh7wm";
// Data values
float batt = 100;
String latitude = "3.0738";
String longitude = "101.4996";
// Timing
unsigned long previousMillis_upload = 0;
unsigned long previousMillis_display = 0;
const long upload_interval = 20000; // 20s
const long display_interval = 1000; // 1s
// Button, LED, Buzzer
#define BUTTON_PIN 14
#define LED_PIN 26
#define BUZZER_PIN 27
bool buttonPressed = false;
// Preferences for saving keypad entry
Preferences preferences;
void setup() {
Serial.begin(9600);
preferences.begin("keypad", false); // flash storage
pinMode(BUTTON_PIN, INPUT_PULLUP);
pinMode(LED_PIN, OUTPUT);
pinMode(BUZZER_PIN, OUTPUT);
digitalWrite(LED_PIN, LOW);
digitalWrite(BUZZER_PIN, LOW);
if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
Serial.println("❌ OLED failed");
while (1);
}
lcd.init();
lcd.backlight();
lcd.setCursor(0, 0); lcd.print("System Booting...");
lcd.setCursor(0, 1); lcd.print("GPS Tracker Ready");
display.clearDisplay();
display.setTextColor(WHITE);
display.setTextSize(1);
display.setCursor(10, 25); display.println("ThingsBoard Uploader");
display.display();
delay(3000);
WiFi.begin(ssid, password);
lcd.clear();
lcd.setCursor(0, 0); lcd.print("Connecting WiFi");
int i = 0;
while (WiFi.status() != WL_CONNECTED && i < 20) {
delay(500);
Serial.print(".");
i++;
}
if (WiFi.status() == WL_CONNECTED) {
Serial.println("\n✅ WiFi Connected!");
lcd.setCursor(0, 1); lcd.print("WiFi Connected!");
} else {
lcd.setCursor(0, 1); lcd.print("WiFi Failed!");
}
delay(2000);
lcd.clear();
lcd.setCursor(0, 0); lcd.print("Enter Value:");
String lastEntry = preferences.getString("entry", "none");
Serial.println("🔎 Last saved entry: " + lastEntry);
}
void loop() {
unsigned long currentMillis = millis();
// Refresh OLED
if (currentMillis - previousMillis_display >= display_interval) {
previousMillis_display = currentMillis;
display.clearDisplay();
display.setTextSize(1);
display.setCursor(0, 0); display.print("Lat: "); display.println(latitude);
display.setCursor(0, 10); display.print("Lng: "); display.println(longitude);
display.setCursor(0, 20); display.print("Batt: "); display.print(batt); display.println(" %");
display.display();
}
// Send periodic telemetry
if (currentMillis - previousMillis_upload >= upload_interval) {
previousMillis_upload = currentMillis;
sendTelemetry(latitude, longitude, batt);
batt -= 0.5; if (batt < 0) batt = 100;
}
// Button triggers LED, buzzer, and sends mark location
if (digitalRead(BUTTON_PIN) == LOW && !buttonPressed) {
buttonPressed = true;
Serial.println("🔘 Button pressed!");
digitalWrite(LED_PIN, HIGH);
digitalWrite(BUZZER_PIN, HIGH);
sendMarkLocation(latitude, longitude);
}
if (digitalRead(BUTTON_PIN) == HIGH) {
buttonPressed = false;
digitalWrite(LED_PIN, LOW);
digitalWrite(BUZZER_PIN, LOW);
}
// Keypad input
char key = keypad.getKey();
if (key) {
Serial.print("Key: "); Serial.println(key);
if (key >= '0' && key <= '9') {
keypadBuffer += key;
lcd.clear();
lcd.setCursor(0, 0); lcd.print("Enter Value:");
lcd.setCursor(0, 1); lcd.print(keypadBuffer);
} else if (key == '#') {
if (keypadBuffer.length() > 0) {
lcd.clear();
lcd.setCursor(0, 0); lcd.print("Sending & Saving...");
sendKeypadValue(keypadBuffer);
preferences.putString("entry", keypadBuffer);
lcd.setCursor(0, 1); lcd.print("Data Sent!");
delay(2000);
keypadBuffer = "";
lcd.clear();
lcd.setCursor(0, 0); lcd.print("Enter Value:");
}
} else if (key == '*') {
keypadBuffer = "";
lcd.clear();
lcd.setCursor(0, 0); lcd.print("Entry Cleared");
delay(1000);
lcd.clear();
lcd.setCursor(0, 0); lcd.print("Enter Value:");
}
}
}
void sendTelemetry(String lat, String lng, float battery) {
if (WiFi.status() != WL_CONNECTED) {
Serial.println("🚫 WiFi not connected!");
return;
}
String url = String(tbServer) + "/api/v1/" + tbToken + "/telemetry";
String payload = "{\"latitude\":" + lat + ",\"longitude\":" + lng + ",\"battery\":" + String(battery) + "}";
HTTPClient http;
http.begin(url);
http.addHeader("Content-Type", "application/json");
int httpCode = http.POST(payload);
if (httpCode > 0) {
Serial.print("✅ Telemetry sent! HTTP "); Serial.println(httpCode);
} else {
Serial.print("❌ Failed telemetry. HTTP "); Serial.println(httpCode);
}
http.end();
}
void sendKeypadValue(String value) {
if (WiFi.status() != WL_CONNECTED) {
Serial.println("🚫 WiFi not connected!");
return;
}
String url = String(tbServer) + "/api/v1/" + tbToken + "/telemetry";
String payload = "{\"keypad_value\":\"" + value + "\"}";
HTTPClient http;
http.begin(url);
http.addHeader("Content-Type", "application/json");
int httpCode = http.POST(payload);
if (httpCode > 0) {
Serial.print("✅ Keypad value sent! HTTP "); Serial.println(httpCode);
} else {
Serial.print("❌ Failed keypad send. HTTP "); Serial.println(httpCode);
}
http.end();
}
void sendMarkLocation(String lat, String lng) {
if (WiFi.status() != WL_CONNECTED) {
Serial.println("🚫 WiFi not connected!");
return;
}
String url = String(tbServer) + "/api/v1/" + tbToken + "/telemetry";
// Updated to overwrite main latitude & longitude
String payload = "{\"latitude\":" + lat + ",\"longitude\":" + lng + "}";
HTTPClient http;
http.begin(url);
http.addHeader("Content-Type", "application/json");
int httpCode = http.POST(payload);
if (httpCode > 0) {
Serial.print("✅ Mark location sent! HTTP "); Serial.println(httpCode);
} else {
Serial.print("❌ Failed to send mark. HTTP "); Serial.println(httpCode);
}
http.end();
}